Fix various possible XSS attacks

This commit is contained in:
Bubka 2023-06-30 14:50:57 +02:00
parent 3d59b8b3c9
commit bac39882c3
6 changed files with 59 additions and 11 deletions

View File

@ -2,6 +2,7 @@
namespace App\Api\v1\Controllers;
use App\Api\v1\Requests\IconFetchRequest;
use App\Http\Controllers\Controller;
use App\Models\TwoFAccount;
use App\Services\LogoService;
@ -34,13 +35,11 @@ public function upload(Request $request)
*
* @return \Illuminate\Http\JsonResponse
*/
public function fetch(Request $request, LogoService $logoService)
public function fetch(IconFetchRequest $request, LogoService $logoService)
{
$this->validate($request, [
'service' => 'string|regex:/^[^:]+$/i',
]);
$validated = $request->validated();
$icon = $logoService->getIcon($request->service);
$icon = $logoService->getIcon($validated['service']);
return $icon
? response()->json(['filename' => $icon], 201)

View File

@ -28,7 +28,7 @@ public function rules()
return [
'name' => [
'required',
'string',
'alpha_dash',
'max:32',
Rule::unique('groups')->where(fn ($query) => $query->where('user_id', $this->user()->id)),
],

View File

@ -0,0 +1,45 @@
<?php
namespace App\Api\v1\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Auth;
class IconFetchRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return Auth::check();
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'service' => 'string|regex:/^[^:]+$/i',
];
}
/**
* Prepare the data for validation.
*
* @codeCoverageIgnore
*
* @return void
*/
protected function prepareForValidation()
{
$this->merge([
'service' => strip_tags($this->service),
]);
}
}

View File

@ -126,6 +126,10 @@ Vue.mixin({
this.setTheme(this.$root.userPreferences.theme)
},
strip_tags (str) {
return str.replace(/(<([^> ]+)>)/ig, "")
}
}
})

View File

@ -149,7 +149,7 @@
<div class="block">
{{ $t('errors.data_of_qrcode_is_not_valid_URI') }}
</div>
<div class="block mb-6" :class="$root.showDarkMode ? 'has-text-light':'has-text-grey-dark'" v-html="uri"></div>
<div class="block mb-6" :class="$root.showDarkMode ? 'has-text-light':'has-text-grey-dark'">{{ uri }}</div>
<!-- Copy to clipboard -->
<div class="block has-text-link">
<button class="button is-link is-outlined is-rounded" v-clipboard="() => uri" v-clipboard:success="clipboardSuccessHandler">
@ -372,10 +372,10 @@
this.deleteIcon()
this.tempIcon = response.data.filename;
}
else this.$notify({type: 'is-warning', text: this.$t('errors.no_logo_found_for_x', {service: this.form.service}) })
else this.$notify({type: 'is-warning', text: this.$t('errors.no_logo_found_for_x', {service: this.strip_tags(this.form.service)}) })
})
.catch(error => {
this.$notify({type: 'is-warning', text: this.$t('errors.no_logo_found_for_x', {service: this.form.service}) })
this.$notify({type: 'is-warning', text: this.$t('errors.no_logo_found_for_x', {service: this.strip_tags(this.form.service)}) })
});
}
},

View File

@ -265,10 +265,10 @@
this.deleteIcon()
this.tempIcon = response.data.filename;
}
else this.$notify({type: 'is-warning', text: this.$t('errors.no_logo_found_for_x', {service: this.form.service}) })
else this.$notify({type: 'is-warning', text: this.$t('errors.no_logo_found_for_x', {service: this.strip_tags(this.form.service)}) })
})
.catch(error => {
this.$notify({type: 'is-warning', text: this.$t('errors.no_logo_found_for_x', {service: this.form.service}) })
this.$notify({type: 'is-warning', text: this.$t('errors.no_logo_found_for_x', {service: this.strip_tags(this.form.service)}) })
});
}
},