Kibble API griefing
Theory:
Apache Kibble only supports cookie authorization for its REST API.
Attempt(s) to falsify the above:
GET http://localhost:9200/kibble_useraccount/_search?pretty HTTP/1.1
Content-Type: application/json
{
"query": {
"match_all": {}
}
}
HTTP/1.1 200 OK
content-type: application/json; charset=UTF-8
content-encoding: gzip
content-length: 458
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 1.0,
"hits": [
{
"_index": "kibble_useraccount",
"_type": "_doc",
"_id": "[email protected]",
"_score": 1.0,
"_source": {
"email": "[email protected]",
"password": "blah-blah-blah",
"displayName": "Administrator",
"organisations": [],
"ownerships": [],
"defaultOrganisation": "Blah",
"verified": true,
"userlevel": "admin",
"token": "abdb02d7-6450-4af2-9ef3-add42907e09c"
}
}
]
}
}
Great we have a "token". Let's see what that does:
POST http://kibble.localhost/api/org/list HTTP/1.1
Authorization: token abdb02d7-6450-4af2-9ef3-add42907e09c
Content-Type: application/json
HTTP/1.1 403 Authentication failed
Date: Wed, 27 May 2020 17:29:05 GMT
Server: gunicorn/20.0.4
Content-Type: application/json
Connection: close
Transfer-Encoding: chunked
{
"code": 403,
"reason": "You must be logged in to use this API endpoint!"
}
Hmm, nothing. Let's attempt traditional authorization schemes. Note that my REST client automatically Base64 encodes 'user pass'.
POST http://kibble.localhost/api/org/list HTTP/1.1
Authorization: Basic [email protected] blah-blah-blah
Content-Type: application/json
and
POST http://kibble.localhost/api/org/list HTTP/1.1
Authorization: Digest [email protected] blah-blah-blah
Content-Type: application/json
both result in:
HTTP/1.1 403 Authentication failed
Date: Wed, 27 May 2020 17:32:52 GMT
Server: gunicorn/20.0.4
Content-Type: application/json
Connection: close
Transfer-Encoding: chunked
{
"code": 403,
"reason": "You must be logged in to use this API endpoint!"
}
Hmm. Let's fiddle with kibble_uisession and see where that leads.
GET http://localhost:9200/kibble_uisession/_search?pretty HTTP/1.1
Content-Type: application/json
{
"query": {
"match_all": {}
}
}
HTTP/1.1 200 OK
content-type: application/json; charset=UTF-8
content-encoding: gzip
content-length: 554
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 8,
"relation": "eq"
},
"max_score": 1.0,
"hits": [
{
"_index": "kibble_uisession",
"_type": "_doc",
"_id": "1a50a63a-c30b-4eae-9d5d-ee3a60d5774a",
"_score": 1.0,
"_source": {
"cid": "[email protected]",
"id": "1a50a63a-c30b-4eae-9d5d-ee3a60d5774a",
"timestamp": 1588490569
}
},
{
"_index": "kibble_uisession",
"_type": "_doc",
"_id": "d111112e-0a56-4345-a826-628e82474d6b",
"_score": 1.0,
"_source": {
"cid": "[email protected]",
"id": "d111112e-0a56-4345-a826-628e82474d6b",
"timestamp": 1590598956
}
},
{
"_index": "kibble_uisession",
"_type": "_doc",
"_id": "GLhx2XEBNsvtLM3qCx7P",
"_score": 1.0,
"_source": {
"cid": "[email protected]",
"id": null,
"timestamp": 1588490996
}
},
{
"_index": "kibble_uisession",
"_type": "_doc",
"_id": "pPfjUnIBipkYliznO657",
"_score": 1.0,
"_source": {
"cid": "[email protected]",
"id": null,
"timestamp": 1590528523
}
},
{
"_index": "kibble_uisession",
"_type": "_doc",
"_id": "4322a9ac-6654-44c2-9b29-1859b2c457e4",
"_score": 1.0,
"_source": {
"cid": "[email protected]",
"id": "4322a9ac-6654-44c2-9b29-1859b2c457e4",
"timestamp": 1590599702
}
},
{
"_index": "kibble_uisession",
"_type": "_doc",
"_id": "kgDJVnIBXVmZaGAJjxn6",
"_score": 1.0,
"_source": {
"cid": "[email protected]",
"id": null,
"timestamp": 1590593949
}
},
{
"_index": "kibble_uisession",
"_type": "_doc",
"_id": "114ed171-9fe1-42fd-9b3d-b7622c438ae4",
"_score": 1.0,
"_source": {
"cid": "[email protected]",
"id": "114ed171-9fe1-42fd-9b3d-b7622c438ae4",
"timestamp": 1590594038
}
},
{
"_index": "kibble_uisession",
"_type": "_doc",
"_id": "kQDQVnIBXVmZaGAJsipG",
"_score": 1.0,
"_source": {
"cid": "[email protected]",
"id": null,
"timestamp": 1590594417
}
}
]
}
}
Oh, hello! Let's see what gives.
POST http://kibble.localhost/api/org/list HTTP/1.1
Cookie: kibble_session=d111112e-0a56-4345-a826-628e82474d6b
Content-Type: application/json
HTTP/1.1 200 Okay
Date: Wed, 27 May 2020 17:46:40 GMT
Server: gunicorn/20.0.4
Content-Type: application/json; charset=utf-8
Connection: close
Transfer-Encoding: chunked
{
"organisations": [
{
"id": "2e1c2450",
"name": "blah1",
"description": "blah description",
"admins": [],
"sourceCount": 0,
"docCount": 16709
},
{
"id": "blah2",
"name": "blah2",
"description": "blah description",
"admins": [],
"sourceCount": 0,
"docCount": 22881
}
],
"okay": true,
"responseTime": 0.17593073844909668
}
Conclusion: I have failed to refute the initial theory. Can anyone refute this and if not, comment on any plans available to provide proper authorization scheme for REST Clients?
the token fetched from the preferences URI must currently be handed in the Kibble-Token header of the request, such as in this python example:
issues = requests.post('https://demo.kibble.apache.org/api/issue/issues',
headers = {
'Content-Type': 'application/json',
'Kibble-Token': TOKEN,
},
json = {
"page":"issues",
"quick":True,
"interval": "week",
"subfilter":"/(?:incubator-)?" + project + ".*\\.git",
"distinguish":True
}
).json()
It would be nice if it accepted a token in the Authorization header as well, and when I'm back home, I'll work on making that happen.
I'll also add that the token should be easily visible to the user, which means working on the user interface some more..