Repository navigation
Appstore should check for valid certificate #249
Description
With 11.0, we will enable the certificate check for apps from the appstore by default. This offers the following advantages:
- If the appstore is hacked it won't be possible to deliver malicious updates (since the updates have to be signed)
- We don't have to do this enormous kind of moderation we did on https://apps.owncloud.com/ with all the spam uploads. If an app is not signed we don't need to display it at all.
While this is a little bit of additional work for the dev, requesting the certificate is quick and easy: https://docs.nextcloud.com/server/10/developer_manual/app/code_signing.html#how-to-get-your-app-signed
Additionally, this is also required for a proper user experience when updating form an older version. Basically for updates we use the app ID now and to avoid any issues with having somebody else claim an app ID we need to ensure those are signed. While the verification on the Nextcloud side is in place, it still is possible to spam the app list.
Technical implementation
I don't think it's necessary to validate the signature, that one the server can do. But we should check for a valid certificate.
Basically in appinfo/signature.json there is a text field certificate, that one looks as following:
"certificate": "-----BEGIN CERTIFICATE-----\r\nMIIEojCCA4qgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwezELMAkGA1UEBhMCREUx\r\nGzAZBgNVBAgMEkJhZGVuLVd1ZXJ0dGVtYmVyZzEXMBUGA1UECgwOTmV4dGNsb3Vk\r\nI
EdtYkgxNjA0BgNVBAMMLU5leHRjbG91ZCBDb2RlIFNpZ25pbmcgSW50ZXJtZWRp\r\nYXRlIEF1dGhvcml0eTAeFw0xNjA2MTIyMTA1MDZaFw00MTA2MDYyMTA1MDZaMGYx\r\nCzAJBgNVBAYTAkRFMRswGQYDVQQIDBJCYWRlbi1XdWVydHRlbWJlc
mcxEjAQBgNV\r\nBAcMCVN0dXR0Z2FydDEXMBUGA1UECgwOTmV4dGNsb3VkIEdtYkgxDTALBgNVBAMM\r\nBGNvcmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDUxcrn2DC892IX\r\n8+dJjZVh9YeHF65n2ha886oeAizOuHBdWBfzq
t+GoUYTOjqZF93HZMcwy0P+xyCf\r\nQqak5Ke9dybN06RXUuGP45k9UYBp03qzlUzCDalrkj+Jd30LqcSC1sjRTsfuhc+u\r\nvH1IBuBnf7SMUJUcoEffbmmpAPlEcLHxlUGlGnz0q1e8UFzjbEFj3JucMO4ys35F\r\nqZS4dhvCngQhRW3DaMlQL
XEUL9k3kFV+BzlkPzVZEtSmk4HJujFCnZj1vMcjQBg\/\r\nBqq1HCmUB6tulnGcxUzt\/Z\/oSIgnuGyENeke077W3EyryINL7EIyD4Xp7sxLizTM\r\nFCFCjjH1AgMBAAGjggFDMIIBPzAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIG\r\nQD
AzBglghkgBhvhCAQ0EJhYkT3BlblNTTCBHZW5lcmF0ZWQgU2VydmVyIENlcnRp\r\nZmljYXRlMB0GA1UdDgQWBBQwc1H9AL8pRlW2e5SLCfPPqtqc0DCBpQYDVR0jBIGd\r\nMIGagBRt6m6qqTcsPIktFz79Ru7DnnjtdKF+pHwwejELMAkGA1UEBh
MCREUxGzAZ\r\nBgNVBAgMEkJhZGVuLVd1ZXJ0dGVtYmVyZzESMBAGA1UEBwwJU3R1dHRnYXJ0MRcw\r\nFQYDVQQKDA5OZXh0Y2xvdWQgR21iSDEhMB8GA1UEAwwYTmV4dGNsb3VkIFJvb3Qg\r\nQXV0aG9yaXR5ggIQADAOBgNVHQ8BAf8EBAMCBa
AwEwYDVR0lBAwwCgYIKwYBBQUH\r\nAwEwDQYJKoZIhvcNAQELBQADggEBADZ6+HV\/+0NEH3nahTBFxO6nKyR\/VWigACH0\r\nnaV0ecTcoQwDjKDNNFr+4S1WlHdwITlnNabC7v9rZ\/6QvbkrOTuO9fOR6azp1EwW\r\n2pixWqj0Sb9\/dSIVRp
Sq+jpBE6JAiX44dSR7zoBxRB8DgVO2Afy0s80xEpr5JAzb\r\nNYuPS7M5UHdAv2dr16fDcDIvn+vk92KpNh1NTeZFjBbRVQ9DXrgkRGW34TK8uSLI\r\nYG6jnfJ6eJgTaO431ywWPXNg1mUMaT\/+QBOgB299QVCKQU+lcZWptQt+RdsJUm46\r\nN
Y\/nARy4Oi4uOe88SuWITj9KhrFmEvrUlgM8FvoXA1ldrR7KiEg=\r\n-----END CERTIFICATE-----"
This decodes to:
-----BEGIN CERTIFICATE-----
MIIEojCCA4qgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwezELMAkGA1UEBhMCREUx
GzAZBgNVBAgMEkJhZGVuLVd1ZXJ0dGVtYmVyZzEXMBUGA1UECgwOTmV4dGNsb3Vk
I
EdtYkgxNjA0BgNVBAMMLU5leHRjbG91ZCBDb2RlIFNpZ25pbmcgSW50ZXJtZWRp
YXRlIEF1dGhvcml0eTAeFw0xNjA2MTIyMTA1MDZaFw00MTA2MDYyMTA1MDZaMGYx
CzAJBgNVBAYTAkRFMRswGQYDVQQIDBJCYWRlbi1XdWVydHRlbWJlc
mcxEjAQBgNV
BAcMCVN0dXR0Z2FydDEXMBUGA1UECgwOTmV4dGNsb3VkIEdtYkgxDTALBgNVBAMM
BGNvcmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDUxcrn2DC892IX
8+dJjZVh9YeHF65n2ha886oeAizOuHBdWBfzq
t+GoUYTOjqZF93HZMcwy0P+xyCf
Qqak5Ke9dybN06RXUuGP45k9UYBp03qzlUzCDalrkj+Jd30LqcSC1sjRTsfuhc+u
vH1IBuBnf7SMUJUcoEffbmmpAPlEcLHxlUGlGnz0q1e8UFzjbEFj3JucMO4ys35F
qZS4dhvCngQhRW3DaMlQL
XEUL9k3kFV+BzlkPzVZEtSmk4HJujFCnZj1vMcjQBg
/
Bqq1HCmUB6tulnGcxUzt
/Z
/oSIgnuGyENeke077W3EyryINL7EIyD4Xp7sxLizTM
FCFCjjH1AgMBAAGjggFDMIIBPzAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIG
QD
AzBglghkgBhvhCAQ0EJhYkT3BlblNTTCBHZW5lcmF0ZWQgU2VydmVyIENlcnRp
ZmljYXRlMB0GA1UdDgQWBBQwc1H9AL8pRlW2e5SLCfPPqtqc0DCBpQYDVR0jBIGd
MIGagBRt6m6qqTcsPIktFz79Ru7DnnjtdKF+pHwwejELMAkGA1UEBh
MCREUxGzAZ
BgNVBAgMEkJhZGVuLVd1ZXJ0dGVtYmVyZzESMBAGA1UEBwwJU3R1dHRnYXJ0MRcw
FQYDVQQKDA5OZXh0Y2xvdWQgR21iSDEhMB8GA1UEAwwYTmV4dGNsb3VkIFJvb3Qg
QXV0aG9yaXR5ggIQADAOBgNVHQ8BAf8EBAMCBa
AwEwYDVR0lBAwwCgYIKwYBBQUH
AwEwDQYJKoZIhvcNAQELBQADggEBADZ6+HV
/+0NEH3nahTBFxO6nKyR
/VWigACH0
naV0ecTcoQwDjKDNNFr+4S1WlHdwITlnNabC7v9rZ
/6QvbkrOTuO9fOR6azp1EwW
2pixWqj0Sb9
/dSIVRp
Sq+jpBE6JAiX44dSR7zoBxRB8DgVO2Afy0s80xEpr5JAzb
NYuPS7M5UHdAv2dr16fDcDIvn+vk92KpNh1NTeZFjBbRVQ9DXrgkRGW34TK8uSLI
YG6jnfJ6eJgTaO431ywWPXNg1mUMaT
/+QBOgB299QVCKQU+lcZWptQt+RdsJUm46
N
Y
/nARy4Oi4uOe88SuWITj9KhrFmEvrUlgM8FvoXA1ldrR7KiEg=
-----END CERTIFICATE-----
lukasreschke@nextcloud-dev:/media/psf/nextcloud$ openssl x509 -in cert.crt -text -noout
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 4096 (0x1000)
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=DE, ST=Baden-Wuerttemberg, O=Nextcloud GmbH, CN=Nextcloud Code Signing Intermediate Authority
Validity
Not Before: Jun 12 21:05:06 2016 GMT
Not After : Jun 6 21:05:06 2041 GMT
Subject: C=DE, ST=Baden-Wuerttemberg, L=Stuttgart, O=Nextcloud GmbH, CN=core
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:d4:c5:ca:e7:d8:30:bc:f7:62:17:f3:e7:49:8d:
95:61:f5:87:87:17:ae:67:da:16:bc:f3:aa:1e:02:
2c:ce:b8:70:5d:58:17:f3:aa:df:86:a1:46:13:3a:
3a:99:17:dd:c7:64:c7:30:cb:43:fe:c7:20:9f:42:
a6:a4:e4:a7:bd:77:26:cd:d3:a4:57:52:e1:8f:e3:
99:3d:51:80:69:d3:7a:b3:95:4c:c2:0d:a9:6b:92:
3f:89:77:7d:0b:a9:c4:82:d6:c8:d1:4e:c7:ee:85:
cf:ae:bc:7d:48:06:e0:67:7f:b4:8c:50:95:1c:a0:
47:df:6e:69:a9:00:f9:44:70:b1:f1:95:41:a5:1a:
7c:f4:ab:57:bc:50:5c:e3:6c:41:63:dc:9b:9c:30:
ee:32:b3:7e:45:a9:94:b8:76:1b:c2:9e:04:21:45:
6d:c3:68:c9:50:2d:71:14:2f:d9:37:90:55:7e:07:
39:64:3f:35:59:12:d4:a6:93:81:c9:ba:31:42:9d:
98:f5:bc:c7:23:40:18:3f:06:aa:b5:1c:29:94:07:
ab:6e:96:71:9c:c5:4c:ed:fd:9f:e8:48:88:27:b8:
6c:84:35:e9:1e:d3:be:d6:dc:4c:ab:c8:83:4b:ec:
42:32:0f:85:e9:ee:cc:4b:8b:34:cc:14:21:42:8e:
31:f5
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Cert Type:
SSL Server
Netscape Comment:
OpenSSL Generated Server Certificate
X509v3 Subject Key Identifier:
30:73:51:FD:00:BF:29:46:55:B6:7B:94:8B:09:F3:CF:AA:DA:9C:D0
X509v3 Authority Key Identifier:
keyid:6D:EA:6E:AA:A9:37:2C:3C:89:2D:17:3E:FD:46:EE:C3:9E:78:ED:74
DirName:/C=DE/ST=Baden-Wuerttemberg/L=Stuttgart/O=Nextcloud GmbH/CN=Nextcloud Root Authority
serial:10:00
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Server Authentication
Signature Algorithm: sha256WithRSAEncryption
36:7a:f8:75:7f:fb:43:44:1f:79:da:85:30:45:c4:ee:a7:2b:
24:7f:55:68:a0:00:21:f4:9d:a5:74:79:c4:dc:a1:0c:03:8c:
a0:cd:34:5a:fe:e1:2d:56:94:77:70:21:39:67:35:a6:c2:ee:
ff:6b:67:fe:90:bd:b9:2b:39:3b:8e:f5:f3:91:e9:ac:e9:d4:
4c:16:da:98:b1:5a:a8:f4:49:bf:7f:75:22:15:46:94:aa:fa:
3a:41:13:a2:40:89:7e:38:75:24:7b:ce:80:71:44:1f:03:81:
53:b6:01:fc:b4:b3:cd:31:12:9a:f9:24:0c:db:35:8b:8f:4b:
b3:39:50:77:40:bf:67:6b:d7:a7:c3:70:32:2f:9f:eb:e4:f7:
62:a9:36:1d:4d:4d:e6:45:8c:16:d1:55:0f:43:5e:b8:24:44:
65:b7:e1:32:bc:b9:22:c8:60:6e:a3:9d:f2:7a:78:98:13:68:
ee:37:d7:2c:16:3d:73:60:d6:65:0c:69:3f:fe:40:13:a0:07:
6f:7d:41:50:8a:41:4f:a5:71:95:a9:b5:0b:7e:45:db:09:52:
6e:3a:35:8f:e7:01:1c:b8:3a:2e:2e:39:ef:3c:4a:e5:88:4e:
3f:4a:86:b1:66:12:fa:d4:96:03:3c:16:fa:17:03:59:5d:ad:
1e:ca:88:48
What has to happen here is:
- The server has to check if the CN matches the app id. (here:
core) - The server has to check if the certificate is issued by the
Nextcloud Code Signing Intermediate Authority. You can find the certs at https://github.com/nextcloud/server/blob/master/resources/codesigning/root.crt
If not: Throw an error.
Activity
LukasReschke commentedon Sep 7, 2016
Moving to 0.1.0 as discussed with @BernhardPosselt. http://aviadas.com/blog/2015/06/18/verifying-x509-certificate-chain-of-trust-in-python/ shows how this could be done.
LukasReschke commentedon Sep 8, 2016
Ok. We go with an easier way of signing, basically the tar files have to be signed used
openssl dgst -sha256 -sign /Users/lukasreschke/Documents/Programming/nextcloud/stable9/tests/data/integritycheck/SomeApp.Key app.tar.bz2 | openssl base64. The PHP implementation can be found at https://gist.github.com/LukasReschke/f1f91925291495ec2e388bb3eaac6989The appstore needs to deliver the certificate and the signature and that's it.
BernhardPosselt commentedon Sep 8, 2016
Closed in favor of new separate tickets