fix XSS on opengraph tags

This commit is contained in:
2020-12-07 22:23:29 +01:00
parent 69e3a34d86
commit e35e6b0f45
8 changed files with 95 additions and 97 deletions

View File

@@ -65,4 +65,4 @@ See our subscription plans on Patreon
After ordering you will receive an e-mail with a link to activate your After ordering you will receive an e-mail with a link to activate your
subscription. The subscription will be linked to the pixeldrain account you're subscription. The subscription will be linked to the pixeldrain account you're
currently loggin into. currently logged into.

View File

@@ -24,7 +24,7 @@
{{template `modal.css`}} {{template `modal.css`}}
</style> </style>
{{.OGData}} {{ template "opengraph" .OGData }}
</head> </head>
<body> <body>
@@ -81,19 +81,17 @@
{{ if and .Other.FileAdsEnabled .Other.UserAdsEnabled }} {{ if and .Other.FileAdsEnabled .Other.UserAdsEnabled }}
<hr/> <hr/>
<div style="text-align: center; line-height: 1.4em"> Tired of ads?<br/>
<!-- scrolling="no" is not allowed by the W3C, but overflow: hidden doesn't work in chrome, so I have no choice --> Files expiring too soon?<br/>
<iframe <a class="button button_highlight" href="/click/7wy9gg2J?target=%2Fsubscribe">
data-aa="73974" <svg style="float: left; width: 2em; height: 2em; fill: currentColor;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
src="//ad.a-ads.com/73974?size=120x600&background_color={{.Style.Layer1Color.RGB}}&text_color={{.Style.TextColor.RGB}}&title_color={{.Style.HighlightColor.RGB}}&title_hover_color={{.Style.HighlightColor.RGB}}&link_color={{.Style.HighlightColor.RGB}}&link_hover_color={{.Style.HighlightColor.RGB}}" <g fill-rule="evenodd">
style="width:120px; height:600px; border:none; padding:0; overflow:hidden;" <path d="M64.1102,0.1004 C44.259,0.1004 28.1086,16.2486 28.1086,36.0986 C28.1086,55.8884 44.259,71.989 64.1102,71.989 C83.9,71.989 100,55.8884 100,36.0986 C100,16.2486 83.9,0.1004 64.1102,0.1004"/>
scrolling="no"> <polygon points=".012 95.988 17.59 95.988 17.59 .1 .012 .1"/>
</iframe> </g>
<br/> </svg>
<a class="button" href="https://a-ads.com/campaigns/new?selected_ad_unit_id=73974&selected_source_type=ad_unit&partner=73974"> Become a Patron!
Put your own advertisement here </a>
</a>
</div>
{{ end }} {{ end }}
<!-- This frame will load the download URL when a download button is pressed --> <!-- This frame will load the download URL when a download button is pressed -->

View File

@@ -23,7 +23,7 @@
{{template `viewer.css`}} {{template `viewer.css`}}
</style> </style>
{{.OGData}} {{ template "opengraph" .OGData }}
</head> </head>
<body> <body>

View File

@@ -19,7 +19,7 @@
<link rel="shortcut icon" sizes="196x196" href="/res/img/pixeldrain_196.png" /> <link rel="shortcut icon" sizes="196x196" href="/res/img/pixeldrain_196.png" />
<meta name="theme-color" content="#75AD38"/> <meta name="theme-color" content="#75AD38"/>
{{.OGData}} {{ template "opengraph" .OGData }}
<script> <script>
const initialNode = {{.Other}}; const initialNode = {{.Other}};
window.api_endpoint = '{{.APIEndpoint}}'; window.api_endpoint = '{{.APIEndpoint}}';

View File

@@ -0,0 +1,13 @@
{{ define "opengraph" }}
{{ range $kv := .OGRules }}
<meta property="{{ $kv.Key }}" content="{{ $kv.Value }}" />
{{ end }}
{{ range $kv := .TwitterRules }}
<meta name="{{ $kv.Key }}" content="{{ $kv.Value }}" />
{{ end }}
{{ range $kv := .LinkRules }}
<link rel="{{ $kv.Key }}" href="{{ $kv.Value }}" />
{{ end }}
{{ end }}

View File

@@ -44,12 +44,12 @@ func adType() int {
// Intn returns a number up to n, but never n itself. So to get a random 0 // Intn returns a number up to n, but never n itself. So to get a random 0
// or 1 we need to give it n=2. We can use this function to make other // or 1 we need to give it n=2. We can use this function to make other
// splits like 1/3 1/4, etc // splits like 1/3 1/4, etc
switch i := rand.Intn(8); i { switch i := rand.Intn(10); i {
case 0, 1, 2, 3: case 0, 1:
return amarulaSolutions return amarulaSolutions
case 4, 5: case 2, 3, 4:
return adMaven return adMaven
case 6, 7: case 5, 6, 7, 8, 9:
return propellerAds return propellerAds
default: default:
panic(fmt.Errorf( panic(fmt.Errorf(
@@ -282,7 +282,6 @@ func (wc *WebController) serveSkynetViewer(w http.ResponseWriter, r *http.Reques
name = params["filename"] name = params["filename"]
} }
templateData.OGData = ""
templateData.Title = fmt.Sprintf("name ~ Skynet") templateData.Title = fmt.Sprintf("name ~ Skynet")
templateData.Other = viewerData{ templateData.Other = viewerData{
Type: "skylink", Type: "skylink",

View File

@@ -1,99 +1,87 @@
package webcontroller package webcontroller
import ( import (
"html/template"
"strings" "strings"
"fornaxian.tech/pixeldrain_server/api/restapi/apitype" "fornaxian.tech/pixeldrain_server/api/restapi/apitype"
) )
type ogRule struct { type ogData struct {
Prop string OGRules []ogProp
Content string TwitterRules []ogProp
LinkRules []ogProp
} }
func (o ogRule) HTML() template.HTML { type ogProp struct {
return template.HTML(`<meta property="` + o.Prop + `" content="` + o.Content + `"/>` + "\n") Key string
Value string
} }
type twitterRule struct { func (og *ogData) addOG(k, v string) { og.OGRules = append(og.OGRules, ogProp{k, v}) }
Name string func (og *ogData) addTwitter(k, v string) { og.TwitterRules = append(og.TwitterRules, ogProp{k, v}) }
Content string func (og *ogData) addLink(k, v string) { og.LinkRules = append(og.LinkRules, ogProp{k, v}) }
}
func (o twitterRule) HTML() template.HTML { func metadataFromFile(f apitype.FileInfo) (og ogData) {
return template.HTML(`<meta name="` + o.Name + `" content="` + o.Content + `"/>` + "\n") og.addOG("og:title", f.Name)
} og.addOG("og:site_name", "pixeldrain")
og.addOG("og:description", "View '"+f.Name+"' on pixeldrain")
type linkRule struct { og.addOG("description", "View '"+f.Name+"' on pixeldrain")
Rel string og.addOG("og:url", "/u/"+f.ID)
HREF string og.addTwitter("twitter:title", f.Name)
} og.addTwitter("twitter:site", "@Fornax96")
og.addTwitter("twitter:domain", "pixeldrain.com")
func (o linkRule) HTML() template.HTML {
return template.HTML(`<link rel="` + o.Rel + `" href="` + o.HREF + `"/>` + "\n")
}
func metadataFromFile(f apitype.FileInfo) (meta template.HTML) {
meta += ogRule{"og:title", f.Name}.HTML()
meta += ogRule{"og:site_name", "pixeldrain"}.HTML()
meta += ogRule{"og:description", "View '" + f.Name + "' on pixeldrain"}.HTML()
meta += ogRule{"description", "View '" + f.Name + "' on pixeldrain"}.HTML()
meta += ogRule{"og:url", "/u/" + f.ID}.HTML()
meta += twitterRule{"twitter:title", f.Name}.HTML()
meta += twitterRule{"twitter:site", "@Fornax96"}.HTML()
meta += twitterRule{"twitter:domain", "pixeldrain.com"}.HTML()
if strings.HasPrefix(f.MimeType, "image") { if strings.HasPrefix(f.MimeType, "image") {
meta += ogRule{"og:type", "article"}.HTML() og.addOG("og:type", "article")
meta += ogRule{"og:image", "/api/file/" + f.ID}.HTML() og.addOG("og:image", "/api/file/"+f.ID)
meta += ogRule{"og:image:url", "/api/file/" + f.ID}.HTML() og.addOG("og:image:url", "/api/file/"+f.ID)
meta += ogRule{"og:image:secure_url", "/api/file/" + f.ID}.HTML() og.addOG("og:image:secure_url", "/api/file/"+f.ID)
meta += ogRule{"og:image:type", f.MimeType}.HTML() og.addOG("og:image:type", f.MimeType)
meta += twitterRule{"twitter:card", "summary_large_image"}.HTML() og.addTwitter("twitter:card", "summary_large_image")
meta += twitterRule{"twitter:image", "/api/file/" + f.ID}.HTML() og.addTwitter("twitter:image", "/api/file/"+f.ID)
meta += linkRule{"image_src", "/api/file/" + f.ID}.HTML() og.addLink("image_src", "/api/file/"+f.ID)
} else if strings.HasPrefix(f.MimeType, "video") { } else if strings.HasPrefix(f.MimeType, "video") {
meta += ogRule{"og:type", "video.other"}.HTML() og.addOG("og:type", "video.other")
meta += ogRule{"og:image", "/api/file/" + f.ID + "/thumbnail"}.HTML() og.addOG("og:image", "/api/file/"+f.ID+"/thumbnail")
meta += ogRule{"og:video", "/api/file/" + f.ID}.HTML() og.addOG("og:video", "/api/file/"+f.ID)
meta += ogRule{"og:video:secure_url", "/api/file/" + f.ID}.HTML() og.addOG("og:video:url", "/api/file/"+f.ID)
meta += ogRule{"og:video:type", f.MimeType}.HTML() og.addOG("og:video:secure_url", "/api/file/"+f.ID)
og.addOG("og:video:type", f.MimeType)
meta += twitterRule{"twitter:card", "player"}.HTML() og.addTwitter("twitter:card", "player")
meta += twitterRule{"twitter:image", "/api/file/" + f.ID + "/thumbnail"}.HTML() og.addTwitter("twitter:image", "/api/file/"+f.ID+"/thumbnail")
meta += twitterRule{"twitter:player", "/api/file/" + f.ID}.HTML() og.addTwitter("twitter:player", "/api/file/"+f.ID)
meta += twitterRule{"twitter:player:stream", "/api/file/" + f.ID}.HTML() og.addTwitter("twitter:player:stream", "/api/file/"+f.ID)
meta += twitterRule{"twitter:player:stream:content_type", f.MimeType}.HTML() og.addTwitter("twitter:player:stream:content_type", f.MimeType)
meta += linkRule{"image_src", "/api/file/" + f.ID + "/thumbnail"}.HTML() og.addLink("image_src", "/api/file/"+f.ID+"/thumbnail")
} else if strings.HasPrefix(f.MimeType, "audio") { } else if strings.HasPrefix(f.MimeType, "audio") {
meta += ogRule{"og:type", "music.song"}.HTML() og.addOG("og:type", "music.song")
meta += ogRule{"og:audio", "/api/file/" + f.ID}.HTML() og.addOG("og:audio", "/api/file/"+f.ID)
meta += ogRule{"og:audio:secure_url", "/api/file/" + f.ID}.HTML() og.addOG("og:audio:secure_url", "/api/file/"+f.ID)
meta += ogRule{"og:audio:type", f.MimeType}.HTML() og.addOG("og:audio:type", f.MimeType)
meta += linkRule{"image_src", "/api/file/" + f.ID + "/thumbnail"}.HTML() og.addLink("image_src", "/api/file/"+f.ID+"/thumbnail")
} else { } else {
meta += ogRule{"og:type", "website"}.HTML() og.addOG("og:type", "website")
meta += linkRule{"image_src", "/api/file/" + f.ID + "/thumbnail"}.HTML() og.addLink("image_src", "/api/file/"+f.ID+"/thumbnail")
} }
return meta return og
} }
func metadataFromList(l apitype.ListInfo) (meta template.HTML) { func metadataFromList(l apitype.ListInfo) (og ogData) {
meta += ogRule{"og:type", "website"}.HTML() og.addOG("og:type", "website")
meta += ogRule{"og:title", l.Title}.HTML() og.addOG("og:title", l.Title)
meta += ogRule{"og:site_name", "pixeldrain"}.HTML() og.addOG("og:site_name", "pixeldrain")
meta += ogRule{"og:description", "View '" + l.Title + "' on pixeldrain"}.HTML() og.addOG("og:description", "View '"+l.Title+"' on pixeldrain")
meta += ogRule{"description", "View '" + l.Title + "' on pixeldrain"}.HTML() og.addOG("description", "View '"+l.Title+"' on pixeldrain")
meta += ogRule{"og:url", "/l/" + l.ID}.HTML() og.addOG("og:url", "/l/"+l.ID)
meta += twitterRule{"twitter:title", l.Title}.HTML() og.addTwitter("twitter:title", l.Title)
meta += twitterRule{"twitter:site", "@Fornax96"}.HTML() og.addTwitter("twitter:site", "@Fornax96")
meta += twitterRule{"twitter:domain", "pixeldrain.com"}.HTML() og.addTwitter("twitter:domain", "pixeldrain.com")
if l.FileCount > 0 { if l.FileCount > 0 {
meta += ogRule{"og:image", "/api/file/" + l.Files[0].ID + "/thumbnail"}.HTML() og.addOG("og:image", "/api/file/"+l.Files[0].ID+"/thumbnail")
meta += ogRule{"og:image:url", "/api/file/" + l.Files[0].ID + "/thumbnail"}.HTML() og.addOG("og:image:url", "/api/file/"+l.Files[0].ID+"/thumbnail")
meta += twitterRule{"twitter:image", "/api/file/" + l.Files[0].ID + "/thumbnail"}.HTML() og.addTwitter("twitter:image", "/api/file/"+l.Files[0].ID+"/thumbnail")
meta += linkRule{"image_src", "/api/file/" + l.Files[0].ID + "/thumbnail"}.HTML() og.addLink("image_src", "/api/file/"+l.Files[0].ID+"/thumbnail")
} }
return meta return og
} }

View File

@@ -34,7 +34,7 @@ type TemplateData struct {
// Only used on file viewer page // Only used on file viewer page
Title string Title string
OGData template.HTML OGData ogData
Other interface{} Other interface{}
URLQuery url.Values URLQuery url.Values