Adding updated version of ProxyHelper, to force client device traffic to Burp Suite Proxy. Based on the original ProxyHelper by @_kc57

pull/74/head
hoodoer 2024-01-09 11:24:42 -05:00
parent 52d551f504
commit 58a088d2dd
26 changed files with 33424 additions and 0 deletions

View File

@ -0,0 +1,13 @@
# Editor configuration, see https://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 4
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
max_line_length = off
trim_trailing_whitespace = false

46
ProxyHelper2/.gitignore vendored Normal file
View File

@ -0,0 +1,46 @@
# See http://help.github.com/ignore-files/ for more about ignoring files.
# compiled output
/dist
/tmp
/out-tsc
# Only exists if Bazel was run
/bazel-out
# dependencies
/node_modules
# profiling files
chrome-profiler-events*.json
speed-measure-plugin*.json
# IDEs and editors
/.idea
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace
# IDE - VSCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
.history/*
# misc
/.sass-cache
/connect.lock
/coverage
/libpeerconnection.log
npm-debug.log
yarn-error.log
testem.log
/typings
# System Files
.DS_Store
Thumbs.db

47
ProxyHelper2/angular.json Normal file
View File

@ -0,0 +1,47 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"ProxyHelper2": {
"projectType": "library",
"root": "projects/ProxyHelper2",
"sourceRoot": "projects/ProxyHelper2/src",
"prefix": "lib",
"architect": {
"build": {
"builder": "@angular-devkit/build-ng-packagr:build",
"options": {
"tsConfig": "projects/ProxyHelper2/tsconfig.lib.json",
"project": "projects/ProxyHelper2/ng-package.json"
},
"configurations": {
"production": {
"tsConfig": "projects/ProxyHelper2/tsconfig.lib.prod.json"
}
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "projects/ProxyHelper2/src/test.ts",
"tsConfig": "projects/ProxyHelper2/tsconfig.spec.json",
"karmaConfig": "projects/ProxyHelper2/karma.conf.js"
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"projects/ProxyHelper2/tsconfig.lib.json",
"projects/ProxyHelper2/tsconfig.spec.json"
],
"exclude": [
"**/node_modules/**"
]
}
}
}
}},
"defaultProject": "ProxyHelper2"
}

90
ProxyHelper2/build.sh Executable file
View File

@ -0,0 +1,90 @@
#!/bin/bash
MODULENAME=$(basename $PWD)
check_workspace() {
if [[ ! -d "node_modules" ]]; then
while true; do
read -p "[!!] The Angular workspace has not been prepared. Would you like to do it now? [Y\n] " yn
case $yn in
[Yy]* ) prepare_workspace; break;;
[Nn]* ) exit 1;;
* ) prepare_workspace; break;;
esac
done
fi
}
prepare_workspace() {
echo "[*] Preparing the Angular workspace."
if ! command -v npm &> /dev/null; then
echo "[!] NPM does not appear to be installed on this system. Failed to create workspace."
return
fi
if ! npm install &> /dev/null; then
echo "[!] Failed to prepare workspace. Run npm install to see why."
return
fi
echo "[*] Prepared the Angular workspace successfully."
}
build_module() {
ng build --prod > /dev/null 2>&1
RET=$?
if [[ $RET -ne 0 ]]; then
echo "[!] Angular Build Failed: Run 'ng build --prod' to figure out why."
exit 1
else
echo "[*] Angular Build Succeeded"
fi
# Step 2: Copy the required files to the build output
cp -r projects/$MODULENAME/src/module.svg dist/$MODULENAME/bundles/
cp -r projects/$MODULENAME/src/module.json dist/$MODULENAME/bundles/
cp -r projects/$MODULENAME/src/module.py dist/$MODULENAME/bundles/ > /dev/null 2>&1
cp -r projects/$MODULENAME/src/module.php dist/$MODULENAME/bundles/ > /dev/null 2>&1
cp -r projects/$MODULENAME/src/assets/ dist/$MODULENAME/bundles/ > /dev/null 2>&1
# Step 3: Clean up
rm -rf dist/$MODULENAME/bundles/*.map
rm -rf dist/$MODULENAME/bundles/*.min*
rm -rf bundletmp
mv dist/$MODULENAME/bundles/ bundletmp
rm -rf dist/$MODULENAME/*
mv bundletmp/* dist/$MODULENAME/
rm -rf bundletmp
}
package() {
VERS=$(cat dist/$MODULENAME/module.json | grep "version" | awk '{split($0, a, ": "); gsub("\"", "", a[2]); gsub(",", "", a[2]); print a[2]}')
rm -rf $MODULENAME-$VERS.tar.gz
echo "[*] Packaging $MODULENAME (Version $VERS)"
cd dist/
tar -pczf $MODULENAME-$VERS.tar.gz $MODULENAME
mv $MODULENAME-$VERS.tar.gz ../
cd ../
}
copy_to_device() {
echo "[*] Copying module to WiFi Pineapple via SCP"
scp -r dist/$MODULENAME root@172.16.42.1:/pineapple/modules
}
main() {
check_workspace
build_module
if [[ $1 == "package" ]]; then
package
elif [[ $1 == "copy" ]]; then
copy_to_device
fi
echo "[*] Success!"
}
main $1

32223
ProxyHelper2/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

52
ProxyHelper2/package.json Normal file
View File

@ -0,0 +1,52 @@
{
"name": "ProxyHelper2",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
"private": true,
"dependencies": {
"@angular/animations": "~9.1.11",
"@angular/cdk": "^9.2.4",
"@angular/common": "~9.1.11",
"@angular/compiler": "~9.1.11",
"@angular/core": "~9.1.11",
"@angular/flex-layout": "^9.0.0-beta.31",
"@angular/forms": "~9.1.11",
"@angular/material": "^9.2.4",
"@angular/platform-browser": "~9.1.11",
"@angular/platform-browser-dynamic": "~9.1.11",
"@angular/router": "~9.1.11",
"rxjs": "~6.5.5",
"tslib": "^1.10.0",
"zone.js": "~0.10.2"
},
"devDependencies": {
"@angular-devkit/build-angular": "~0.901.8",
"@angular-devkit/build-ng-packagr": "~0.901.8",
"@angular/cli": "~9.1.8",
"@angular/compiler-cli": "~9.1.11",
"@angular/language-service": "~9.1.11",
"@types/jasmine": "~3.5.10",
"@types/jasminewd2": "~2.0.3",
"@types/node": "^12.11.1",
"codelyzer": "^5.1.2",
"jasmine-core": "~3.5.0",
"jasmine-spec-reporter": "~5.0.2",
"karma": "~5.1.0",
"karma-chrome-launcher": "~3.1.0",
"karma-coverage-istanbul-reporter": "~3.0.3",
"karma-jasmine": "~3.3.1",
"karma-jasmine-html-reporter": "^1.4.0",
"ng-packagr": "^9.1.5",
"protractor": "~7.0.0",
"ts-node": "~8.10.2",
"tslint": "~6.1.2",
"typescript": "^3.6.5"
}
}

View File

@ -0,0 +1,7 @@
{
"$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
"dest": "../../dist/ProxyHelper2",
"lib": {
"entryFile": "src/public-api.ts"
}
}

View File

@ -0,0 +1,11 @@
{
"name": "ProxyHelper2",
"version": "0.0.1",
"peerDependencies": {
"@angular/common": "^8.2.14",
"@angular/core": "^8.2.14"
},
"scripts": {
"build": "ng build --prod"
}
}

View File

@ -0,0 +1 @@
This file is a placeholder for module assets that you may like to add.

View File

@ -0,0 +1,27 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ProxyHelper2Component } from './components/ProxyHelper2.component';
import { RouterModule, Routes } from '@angular/router';
import {MaterialModule} from './modules/material/material.module';
import {FlexLayoutModule} from '@angular/flex-layout';
import {FormsModule} from '@angular/forms';
const routes: Routes = [
{ path: '', component: ProxyHelper2Component }
];
@NgModule({
declarations: [ProxyHelper2Component],
imports: [
CommonModule,
RouterModule.forChild(routes),
MaterialModule,
FlexLayoutModule,
FormsModule,
],
exports: [ProxyHelper2Component]
})
export class ProxyHelper2Module { }

View File

@ -0,0 +1,35 @@
.mat-card-content {
padding-bottom: 10px; /* Optional: Add padding for spacing */
}
.mat-card-content + .mat-card-content {
padding-top: 10px; /* Optional: Add padding for spacing */
}
.mat-selection-list {
border: 1px solid #ccc; /* Border color and width */
border-radius: 4px; /* Optional: Add border-radius for rounded corners */
padding: 8px; /* Optional: Add padding for spacing */
max-width: 250px;
}
.mat-list-option {
font-size: 12px;
}
.mat-card {
margin-bottom: 10px; /* Adjust the value to set the desired bottom margin */
}
.mat-flat-button {
height: 28px; /* Adjust the height to make the buttons smaller vertically */
margin-right: 8px; /* Add spacing to the right of each button */
margin-bottom: 8px; /* Add spacing below each button */
align-items: center;
}

View File

@ -0,0 +1,94 @@
<mat-card>
<mat-card-title>Welcome to ProxyHelper2</mat-card-title>
<mat-card-subtitle>Updated version of Kc57's ProxyHelper</mat-card-subtitle>
<mat-card-content>
This module sets the iptables rules to force network traffic of client devices to Burp Suite Proxy. This is useful for mobile applications that do not honor proxy settings on the device.<br>
Enter the ports you would like to force to Burp Suite Proxy, and the IP and port your Burp Suite Proxy is listening on.<br><br>
You'll need to configure your Burp Suite Proxy Listener to listen on all interfaces (not just Loopback only) and set it's Request handling to Support invisible proxying. <br><br>
The github repo for this project is here:<br>
https://github.com/hoodoer/proxy-helper-the-sequel<br><br>
If you have an older pineapple using the older module development style, use the original ProxyHelper module here:<br>
https://github.com/trustedsec/proxy_helper<br>
https://trustedsec.com/blog/introducing-proxy-helper-a-new-wifi-pineapple-module
</mat-card-content>
</mat-card>
<mat-card>
<mat-card-content>
<b>Firewall Rules - Backup and Restore:</b><br><br>
<button mat-flat-button color="primary" (click)="saveFirewallRules();">Backup Firewall Rules</button>
<!-- Loader spinner -->
<div *ngIf="!backendLoaded" class="text-center">
<mat-spinner diameter="100"></mat-spinner>
</div>
<br>
<ul>
<li *ngFor="let backup of backups">
<span style="margin-right: 20px;">{{ backup }}</span>
<button mat-flat-button color="accent" (click)="restoreBackup(backup)">Restore</button>
<button mat-flat-button color="warn" (click)="deleteBackup(backup)">Delete</button>
</li>
</ul>
</mat-card-content>
</mat-card>
<mat-card>
<mat-card-content>
<b>TCP Ports to forward to Burp Proxy:</b><br><br>
<div *ngFor="let port of ports">
<mat-checkbox [(ngModel)]="port.checked" [disabled]="isChecked">{{ port.value }}</mat-checkbox>
</div>
<mat-form-field>
<mat-label>New Port</mat-label>
<input matInput [(ngModel)]="newPort" name="newPort" #newPortInput="ngModel" required pattern="^([1-9]\d{0,4}|[1-5]\d{4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|6553[0-5])$">
<mat-error *ngIf="newPortInput.invalid && (newPortInput.dirty || newPortInput.touched)">
Please enter a valid port number.
</mat-error>
</mat-form-field>
<br>
<button mat-flat-button color="primary" (click)="addNewPort()" [disabled]="newPortInput.invalid || !newPortInput.dirty || isChecked">Add Port</button>
</mat-card-content>
</mat-card>
<mat-card>
<mat-card-content>
<b>Burp Proxy Configuration:</b><br>
<mat-form-field>
<mat-label>IP Address of Proxy</mat-label>
<input matInput [(ngModel)]="proxyIpAddress" name="proxyIpAddress" #ipInput="ngModel" [disabled]="isChecked" required pattern="^((25[0-5]|2[0-4][0-9]|[0-1]?[0-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|[0-1]?[0-9]?[0-9])$">
<mat-error *ngIf="ipInput.invalid && (ipInput.dirty || ipInput.touched)">
Please enter a valid IP address.
</mat-error>
</mat-form-field>
<br>
<mat-form-field>
<mat-label>Port of Proxy</mat-label>
<input matInput [(ngModel)]="proxyPort" name="proxyPort" #portInput="ngModel" [disabled]="isChecked" required pattern="^([1-9]\d{0,4}|[1-5]\d{4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|6553[0-5])$">
<mat-error *ngIf="portInput.invalid && (portInput.dirty || portInput.touched)">
Please enter a valid port number.
</mat-error>
</mat-form-field>
<br>
<mat-slide-toggle [(ngModel)]="isChecked" (change)="routingToggle()" [disabled]="portInput.invalid || !portInput.dirty || ipInput.invalid || !ipInput.dirty">Route to Proxy</mat-slide-toggle>
</mat-card-content>
</mat-card>
<mat-card>
<mat-card-content>
<b><i>Contact Info</i></b><br><br>
If you're having issues feel free to contact me:<br>
@hoodoer<br>
hoodoer@bitwisemunitions.dev
</mat-card-content>
</mat-card>

View File

@ -0,0 +1,148 @@
import { Component, OnInit, ViewEncapsulation, ViewChild } from '@angular/core';
import { ApiService } from '../services/api.service';
import { MatListModule } from '@angular/material/list';
import { MatSelectionList } from '@angular/material/list';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
// import { FormControl, FormGroup, Validators, ReactiveFormsModule, FormBuilder } from '@angular/forms';
@Component({
selector: 'lib-ProxyHelper2',
templateUrl: './ProxyHelper2.component.html',
styleUrls: ['./ProxyHelper2.component.css'],
encapsulation: ViewEncapsulation.None
})
export class ProxyHelper2Component implements OnInit {
constructor(private API: ApiService) { }
@ViewChild('portForwardList') portForwardList: MatSelectionList;
backendLoaded = false;
isChecked = false;
apiResponse = 'Press the button to get response.';
proxyIpAddress = '';
proxyPort = '';
ports = [
{ value: '80', checked: false },
{ value: '443', checked: true },
];
newPort: string = '';
backups: string[] = [];
saveFirewallRules(): void {
this.API.request({
module: 'ProxyHelper2',
action: 'backupFirewall',
}, (response) => {
this.apiResponse = response;
console.log("Save firewall got response: " + response);
console.log("Save firewall error response: " + JSON.stringify(response))
this.backups.push(response);
})
}
deleteBackup(backup: string): void {
console.log("Should delete backup: " + backup)
this.backups = this.backups.filter(i => i !== backup);
this.API.request({
module: 'ProxyHelper2',
action: 'deleteBackup',
backupFile: backup
}, (response) => {
console.log('Delete backup response: ' + response)
});
}
restoreBackup(backup: string): void {
console.log("Would restore firewall backup: " + backup);
this.API.request({
module: 'ProxyHelper2',
action: 'restoreFirewall',
filename: backup
}, (response) => {
console.log("Restore response: " + response);
})
}
getBackups(): void {
console.log("Fetching list of backups on disk...");
this.API.request({
module: 'ProxyHelper2',
action: 'getBackups'
}, (response) => {
console.log("Get backups response: " + response);
console.log(JSON.stringify(response));
this.backups.length = 0;
for (var i = 0; i < response.length; i++) {
this.backups.push(response[i]);
}
this.backendLoaded = true;
})
}
addNewPort(): void {
if (this.newPort && !this.ports.some(port => port.value === this.newPort)) {
this.ports.push({ value: this.newPort, checked: false });
this.newPort = ''; // Clear the input field after adding a new port
}
}
getSelectedPorts(): string[] {
return this.ports.filter(port => port.checked).map(port => port.value);
}
routingToggle(): void {
console.log("Routing toggle changed: " + this.isChecked);
console.log("About to proxy route: " + this.proxyIpAddress + ': ' + this.proxyPort);
var activePorts = this.getSelectedPorts()
console.log("Ports to forward: " + activePorts);
this.API.request({
module: 'ProxyHelper2',
action: 'routingToggle',
toggleValue: this.isChecked,
forwardPorts: activePorts,
proxyHost: this.proxyIpAddress,
proxyPort: this.proxyPort
}, (response) => {
this.apiResponse = response;
console.log("Toggle: " + response);
console.log("details: " + JSON.stringify(response));
})
}
ngOnInit() {
this.getBackups();
}
}

View File

@ -0,0 +1,107 @@
/*
* Copyright (c) 2018 Hak5 LLC.
*/
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { A11yModule } from '@angular/cdk/a11y';
import { BidiModule } from '@angular/cdk/bidi';
import { ObserversModule } from '@angular/cdk/observers';
import { OverlayModule } from '@angular/cdk/overlay';
import { PlatformModule } from '@angular/cdk/platform';
import { PortalModule } from '@angular/cdk/portal';
import { CdkStepperModule } from '@angular/cdk/stepper';
import { CdkTableModule } from '@angular/cdk/table';
import { CdkTreeModule } from '@angular/cdk/tree';
import { MatAutocompleteModule } from '@angular/material/autocomplete';
import { MatBadgeModule } from '@angular/material/badge';
import { MatBottomSheetModule } from '@angular/material/bottom-sheet';
import { MatButtonModule } from '@angular/material/button';
import { MatButtonToggleModule } from '@angular/material/button-toggle';
import { MatCardModule } from '@angular/material/card';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatChipsModule } from '@angular/material/chips';
import { MatNativeDateModule, MatRippleModule } from '@angular/material/core';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatDialogModule } from '@angular/material/dialog';
import { MatDividerModule } from '@angular/material/divider';
import { MatExpansionModule } from '@angular/material/expansion';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatGridListModule } from '@angular/material/grid-list';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { MatListModule } from '@angular/material/list';
import { MatMenuModule } from '@angular/material/menu';
import { MatPaginatorModule } from '@angular/material/paginator';
import { MatProgressBarModule } from '@angular/material/progress-bar';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatRadioModule } from '@angular/material/radio';
import { MatSelectModule } from '@angular/material/select';
import { MatSidenavModule } from '@angular/material/sidenav';
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
import { MatSliderModule } from '@angular/material/slider';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { MatSortModule } from '@angular/material/sort';
import { MatStepperModule } from '@angular/material/stepper';
import { MatTableModule } from '@angular/material/table';
import { MatTabsModule } from '@angular/material/tabs';
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatTooltipModule } from '@angular/material/tooltip';
import { MatTreeModule } from '@angular/material/tree';
@NgModule({
imports: [ CommonModule],
exports: [
// CDK
A11yModule,
BidiModule,
ObserversModule,
OverlayModule,
PlatformModule,
PortalModule,
CdkStepperModule,
CdkTableModule,
CdkTreeModule,
// Material
MatAutocompleteModule,
MatBadgeModule,
MatBottomSheetModule,
MatButtonModule,
MatButtonToggleModule,
MatCardModule,
MatCheckboxModule,
MatChipsModule,
MatDatepickerModule,
MatDialogModule,
MatDividerModule,
MatExpansionModule,
MatFormFieldModule,
MatGridListModule,
MatIconModule,
MatInputModule,
MatListModule,
MatMenuModule,
MatNativeDateModule,
MatPaginatorModule,
MatProgressBarModule,
MatProgressSpinnerModule,
MatRadioModule,
MatRippleModule,
MatSelectModule,
MatSidenavModule,
MatSliderModule,
MatSlideToggleModule,
MatSnackBarModule,
MatSortModule,
MatStepperModule,
MatTableModule,
MatTabsModule,
MatToolbarModule,
MatTooltipModule,
MatTreeModule,
],
declarations: []
})
export class MaterialModule {
}

View File

@ -0,0 +1,8 @@
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class ProxyHelper2Service {
constructor() {}
}

View File

@ -0,0 +1,196 @@
import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {Router} from '@angular/router';
@Injectable({
providedIn: 'root'
})
export class ApiService {
public static totalRequests = 0;
apiModuleBusy = document.getElementById('ApiModuleBusy');
constructor(private http: HttpClient,
private router: Router) {}
emptyResponse = {error: 'Request returned empty response'};
unauth(): void {
localStorage.removeItem('authToken');
if (this.router.url !== '/Login' && this.router.url !== '/Setup') {
this.router.navigateByUrl('/Login');
}
}
setBusy(): void {
this.apiModuleBusy.style.display = 'block';
}
setNotBusy(): void {
this.apiModuleBusy.style.display = 'none';
}
static extractBaseHref(): string {
// Duplicated from injector because we have to be able to support
// a static method here
if (window['_app_base']) {
if (window['_app_base'].endsWith('/')) {
return window['_app_base'].slice(0, -1)
}
}
return window['_app_base'] || '';
}
request(payload: any, callback: (any) => void) {
this.setBusy();
let resp;
this.http.post(`${ApiService.extractBaseHref()}/api/module/request`, payload).subscribe((r: any) => {
if (r === undefined || r === null) {
resp = this.emptyResponse;
} else if (r.error) {
resp = r;
} else {
resp = r.payload;
}
}, (err) => {
resp = err.error;
if (err.status === 401) {
this.unauth();
}
this.setNotBusy();
callback(resp);
}, () => {
this.setNotBusy();
callback(resp);
});
ApiService.totalRequests++;
}
APIGet(path: string, callback: (any) => void): any {
ApiService.totalRequests++;
let resp;
this.http.get(`${ApiService.extractBaseHref()}${path}`).subscribe((r) => {
if (r === undefined || r === null) {
r = this.emptyResponse;
}
resp = r;
}, (err) => {
resp = err.error;
if (err.status === 401) {
this.unauth();
}
callback(resp);
}, () => {
callback(resp);
});
}
async APIGetAsync(path: string): Promise<any> {
ApiService.totalRequests++;
return await this.http.get(`${ApiService.extractBaseHref()}${path}`).toPromise();
}
APIPut(path: string, body: any, callback: (any) => void): any {
ApiService.totalRequests++;
let resp;
this.http.put(`${ApiService.extractBaseHref()}${path}`, body).subscribe((r) => {
if (r === undefined || r === null) {
r = this.emptyResponse;
}
resp = r;
}, (err) => {
resp = err.error;
if (err.status === 401) {
this.unauth();
}
callback(resp);
}, () => {
callback(resp);
});
}
async APIPutAsync(path: string, body: any): Promise<any> {
return await this.http.put(`${ApiService.extractBaseHref()}/${path}`, body).toPromise();
}
APIPost(path: string, body: any, callback: (any) => void): any {
ApiService.totalRequests++;
let resp;
this.http.post(`${ApiService.extractBaseHref()}${path}`, body).subscribe((r) => {
if (r === undefined || r === null) {
resp = this.emptyResponse;
}
resp = r;
}, (err) => {
resp = err.error;
if (err.status === 401) {
this.unauth();
}
callback(resp);
}, () => {
callback(resp);
});
}
async APIPostAsync(path: string, body: any): Promise<any> {
return await this.http.post(`${ApiService.extractBaseHref()}/${path}`, body).toPromise();
}
APIDelete(path: string, body: any, callback: (any) => void): any {
ApiService.totalRequests++;
const opts = {
headers: null,
body: body
};
let resp;
this.http.delete(`${ApiService.extractBaseHref()}/${path}`, opts).subscribe((r) => {
if (r === undefined || r === null) {
r = this.emptyResponse;
}
resp = r;
}, (err) => {
resp = err.error;
if (err.status === 401) {
this.unauth();
}
callback(resp);
}, () => {
callback(resp);
});
}
async APIDeleteAsync(path: string, body: any): Promise<any> {
return await this.http.delete(`${ApiService.extractBaseHref()}${path}`, body).toPromise();
}
APIDownload(fullpath: string, filename: string): void {
ApiService.totalRequests++;
const body = {
filename: fullpath
};
this.http.post(`${ApiService.extractBaseHref()}/api/download`, body, {responseType: 'blob'}).subscribe((r) => {
const url = window.URL.createObjectURL(r);
const a = document.createElement('a');
document.body.appendChild(a);
a.setAttribute('style', 'display: none');
a.href = url;
a.download = filename;
a.click();
window.URL.revokeObjectURL(url);
a.remove();
});
}
}

View File

@ -0,0 +1,10 @@
{
"name": "ProxyHelper2",
"title": "Proxy Helper (The Sequel)",
"description": "Module to force client device TCP traffic to Burp Suite Proxy",
"version": "1.0",
"author": "hoodoer",
"firmware_required": "1.0.0",
"devices": ["wifipineapplemk7"]
}

View File

@ -0,0 +1,123 @@
#!/usr/bin/env python3
import logging
import os
import subprocess
import pathlib
from datetime import datetime
from os import listdir
from pineapple.modules import Module, Request
module = Module('ProxyHelper2', logging.DEBUG)
# This handles the actual forwarding enable/disable
@module.handles_action('routingToggle')
def routingToggle(request: Request):
isChecked = request.toggleValue
ports = request.forwardPorts
proxyIP = request.proxyHost
proxyPort = request.proxyPort
if isChecked:
# Let's enable our forwarding
subprocess.run(["echo", "'1'", ">", "/proc/sys/net/ipv4/ip_forward"], shell=False, check=False)
for port in ports:
burpSpot = proxyIP + ":" + proxyPort
command = ["iptables", "-t", "nat", "-A", "PREROUTING", "-p", "tcp", "--dport", str(port), "-j", "DNAT", "--to-destination", burpSpot]
subprocess.run(command, shell=False, check=False)
result = subprocess.run(["iptables", "-t", "nat", "-A", "POSTROUTING", "-j", "MASQUERADE"], capture_output=True, text=True, shell=False, check=False)
return "Forwarding enabled."
else:
# Turn off forwarding/ clear things
for port in ports:
burpSpot = proxyIP + ":" + proxyPort
command = ["iptables", "-t", "nat", "-D", "PREROUTING", "-p", "tcp", "--dport", str(port), "-j", "DNAT", "--to-destination", burpSpot]
subprocess.run(command, shell=False, check=False)
return 'Forwarding cleared.'
@module.handles_action('backupFirewall')
def backupFirewall(request: Request):
current_time = datetime.now()
formatted_time = current_time.strftime("%Y-%m-%d_%H_%M_%S")
fileName = 'iptables_' + formatted_time;
# save the stuffs....
# These end up in /pineapple/iptablesBackups on the device
backupDir = "./iptablesBackups"
backupPath = os.path.join(backupDir, fileName)
backupCommand = ["iptables-save"]
if not os.path.exists(backupDir):
os.makedirs(backupDir)
with open(backupPath, 'w') as backupFile:
subprocess.run(backupCommand, stdout = backupFile, check=True)
# result = subprocess.run(backupCommand, check=True, shell=True)
return fileName
@module.handles_action('deleteBackup')
def deleteBackup(request: Request):
backupFile = request.backupFile
backupDir = "./iptablesBackups"
filePath = os.path.join(backupDir, backupFile)
deleteCommand = ["rm", filePath]
try:
subprocess.run(" ".join(deleteCommand), shell=True, check=True)
return "Delete backup succeeded: " + backupFile
except:
return "Delete backup failed!" + deleteCommand
@module.handles_action('restoreFirewall')
def restoreFirewall(request: Request):
fileName = request.filename
backupDir = "./iptablesBackups"
restorePath = os.path.join(backupDir, fileName)
restoreCommand = ["iptables-restore", "<", restorePath]
try:
subprocess.run(" ".join(restoreCommand), shell=True, check=True)
return "Restore succeeded: " + fileName
except:
return "Firewall restore failed!"
@module.handles_action('getBackups')
def getBackups(request: Request):
backupDir = "./iptablesBackups"
backupFiles = os.listdir(backupDir)
fileTimes = [(file, os.path.getmtime(os.path.join(backupDir, file))) for file in backupFiles]
sortedBackupFiles = sorted(fileTimes, key=lambda x: x[1])
cleanedBackupFiles = [filename[0] for filename in sortedBackupFiles]
return cleanedBackupFiles
if __name__ == '__main__':
module.start()

View File

@ -0,0 +1 @@
<svg id="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48"><path d="M36.7,16.47V11.66c0-3.48-3.13-4.59-5.81-4.67V1.85c7.3,0,11.62,2.49,11.62,9.24v5.35c0,3.42,2.71,5,5.49,5v5.2c-2.78,0-5.49,1.54-5.49,5v5.35c0,6.75-4.32,9.24-11.62,9.24V41c2.68-.08,5.81-1.19,5.81-4.67V31.53c0-4.11,1.75-6.45,4.22-7.53C38.45,22.92,36.7,20.58,36.7,16.47Zm-25.4,0V11.66c0-3.48,3.13-4.59,5.81-4.67V1.85c-7.3,0-11.62,2.49-11.62,9.24v5.35c0,3.42-2.72,5-5.49,5v5.2c2.77,0,5.49,1.54,5.49,5v5.35c0,6.75,4.32,9.24,11.62,9.24V41c-2.68-.08-5.81-1.19-5.81-4.67V31.53c0-4.11-1.75-6.45-4.22-7.53C9.55,22.92,11.3,20.58,11.3,16.47ZM27.38,26.1H20.57v6.48h2.79a4.69,4.69,0,0,1-2.71,4.14l.68,1.46a7.61,7.61,0,0,0,6.05-7.73Zm0-14H20.57v6.81h6.81Z"/></svg>

After

Width:  |  Height:  |  Size: 726 B

View File

@ -0,0 +1,7 @@
/*
* Public API Surface of ProxyHelper2
*/
export * from './lib/services/ProxyHelper2.service';
export * from './lib/components/ProxyHelper2.component';
export * from './lib/ProxyHelper2.module';

View File

@ -0,0 +1,25 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "../../out-tsc/lib",
"target": "es2015",
"declaration": true,
"inlineSources": true,
"types": [],
"lib": [
"dom",
"es2018"
]
},
"angularCompilerOptions": {
"skipTemplateCodegen": true,
"strictMetadataEmit": true,
"fullTemplateTypeCheck": true,
"strictInjectionParameters": true,
"enableResourceInlining": true
},
"exclude": [
"src/test.ts",
"**/*.spec.ts"
]
}

View File

@ -0,0 +1,6 @@
{
"extends": "./tsconfig.lib.json",
"angularCompilerOptions": {
"enableIvy": false
}
}

View File

@ -0,0 +1,17 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "../../out-tsc/spec",
"types": [
"jasmine",
"node"
]
},
"files": [
"src/test.ts"
],
"include": [
"**/*.spec.ts",
"**/*.d.ts"
]
}

View File

@ -0,0 +1,17 @@
{
"extends": "../../tslint.json",
"rules": {
"directive-selector": [
true,
"attribute",
"lib",
"camelCase"
],
"component-selector": [
true,
"element",
"lib",
"kebab-case"
]
}
}

View File

@ -0,0 +1,34 @@
{
"compileOnSave": false,
"compilerOptions": {
"baseUrl": "./",
"outDir": "./dist/out-tsc",
"sourceMap": true,
"declaration": false,
"downlevelIteration": true,
"experimentalDecorators": true,
"module": "esnext",
"moduleResolution": "node",
"importHelpers": true,
"target": "es2015",
"typeRoots": [
"node_modules/@types"
],
"lib": [
"es2018",
"dom"
],
"paths": {
"ProxyHelper2": [
"dist/ProxyHelper2"
],
"ProxyHelper2/*": [
"dist/ProxyHelper2/*"
]
}
},
"angularCompilerOptions": {
"fullTemplateTypeCheck": true,
"strictInjectionParameters": true
}
}

79
ProxyHelper2/tslint.json Normal file
View File

@ -0,0 +1,79 @@
{
"extends": "tslint:recommended",
"rulesDirectory": [
"codelyzer"
],
"rules": {
"array-type": false,
"arrow-parens": false,
"deprecation": {
"severity": "warning"
},
"import-blacklist": [
true,
"rxjs/Rx"
],
"interface-name": false,
"max-classes-per-file": false,
"max-line-length": [
true,
140
],
"member-access": false,
"member-ordering": [
true,
{
"order": [
"static-field",
"instance-field",
"static-method",
"instance-method"
]
}
],
"no-consecutive-blank-lines": false,
"no-console": [
true,
"debug",
"info",
"time",
"timeEnd",
"trace"
],
"no-empty": false,
"no-inferrable-types": [
true,
"ignore-params"
],
"no-non-null-assertion": true,
"no-redundant-jsdoc": true,
"no-switch-case-fall-through": true,
"no-var-requires": false,
"object-literal-key-quotes": [
true,
"as-needed"
],
"object-literal-sort-keys": false,
"ordered-imports": false,
"quotemark": [
true,
"single"
],
"trailing-comma": false,
"component-class-suffix": true,
"contextual-lifecycle": true,
"directive-class-suffix": true,
"no-conflicting-lifecycle": true,
"no-host-metadata-property": true,
"no-input-rename": true,
"no-inputs-metadata-property": true,
"no-output-native": true,
"no-output-on-prefix": true,
"no-output-rename": true,
"no-outputs-metadata-property": true,
"template-banana-in-box": true,
"template-no-negated-async": true,
"use-lifecycle-interface": true,
"use-pipe-transform-interface": true
}
}