Fuzzing Python Modules
Dmitry Alimov
2018
Fuzzing/fuzz testing
Automated software testing technique that involves providing invalid, unexpected,
or random data as inputs to a program [1]
AFL (American fuzzy lop)
American fuzzy lop – security-oriented fuzzer that employs a novel type of
compile-time instrumentation and genetic algorithms [2]
AFL found vulnerabilities and other bugs in:
tcpdump, ffmpeg, VLC, OpenCV, MySQL, SQLite, PuTTY, wireshark, radare2,
tmux, X.Org Server, PHP, OpenSSL, pngcrush, bash, Firefox, BIND, Qt etc.
AFL (American fuzzy lop)
Install AFL and python wrapper [3]:
$ sudo apt install afl
$ brew install afl-fuzz
$ pip install python-afl
Simple test
import os
import sys
def main():
data = sys.stdin.read()
if len(data) == 2 and data[0] == '1' and data[1] == '2':
raise Exception('BUG!')
os._exit(0)
if __name__ == '__main__':
import afl
afl.start()
main()
AFL config and run
# echo core > /proc/sys/kernel/core_pattern
Maybe skip CPU freq is required: AFL_SKIP_CPUFREQ=1 or update CPUFREQ
settings for CPUs:
# echo performance | tee
/sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
$ py-afl-fuzz -m 500 -t 2000 -i in -o out -- python test.py
Simple test results
Crash found:
./out/crashes/id:000000,sig:10,src:000000,op:havoc,rep:2
$ cat id:000000,sig:10,src:000000,op:havoc,rep:2
12
Test compressed_rtf module
import os
import sys
from compressed_rtf import compress, decompress
def main():
data = sys.stdin.read()
assert decompress(compress(data, compressed=True)) == data
os._exit(0)
if __name__ == '__main__':
import afl
afl.start()
main()
Other tools
- See PythonTestingToolsTaxonomy [5]
- Hypothesis [10]
- zzuf [11]
- your own bicycle [6]
Bug in marshal module
Artem Smotrakov found a bug in marshal module with his own fuzzer [6, 8]:
import marshal
value = ('this is a string', [1, 2, 3, 4], ('more tuples', 1.0, 2.3, 4.5), 'this is
yet another string')
dump = marshal.dumps(value)
data = bytearray(dump)
data[10] = 40
data[4] = 16
data[103] = 143
data[97] = 245
data[78] = 114
data[35] = 188
marshal.loads(bytes(data))
Bug in marshal module
Artem Smotrakov found a bug in marshal module with his own fuzzer [6, 7, 8]:
References
1. https://en.wikipedia.org/wiki/Fuzzing
2. http://lcamtuf.coredump.cx/afl/
3. https://alexgaynor.net/2015/apr/13/introduction-to-fuzzing-in-python-with-afl/
4. https://barro.github.io/2018/01/taking-a-look-at-python-afl/
5. https://wiki.python.org/moin/PythonTestingToolsTaxonomy
6. https://blog.gypsyengineer.com/en/security/python-marshal-module-fuzzing.html
7. https://bugs.python.org/issue27826
8. https://github.com/artem-smotrakov/python-marshal-fuzzer
9. http://tomviner.co.uk/tag/conferences.html
10. https://hypothesis.works/
11. http://caca.zoy.org/wiki/zzuf
12. https://fuzzing-project.org/

Fuzzing python modules

  • 1.
  • 2.
    Fuzzing/fuzz testing Automated softwaretesting technique that involves providing invalid, unexpected, or random data as inputs to a program [1]
  • 3.
    AFL (American fuzzylop) American fuzzy lop – security-oriented fuzzer that employs a novel type of compile-time instrumentation and genetic algorithms [2] AFL found vulnerabilities and other bugs in: tcpdump, ffmpeg, VLC, OpenCV, MySQL, SQLite, PuTTY, wireshark, radare2, tmux, X.Org Server, PHP, OpenSSL, pngcrush, bash, Firefox, BIND, Qt etc.
  • 4.
    AFL (American fuzzylop) Install AFL and python wrapper [3]: $ sudo apt install afl $ brew install afl-fuzz $ pip install python-afl
  • 5.
    Simple test import os importsys def main(): data = sys.stdin.read() if len(data) == 2 and data[0] == '1' and data[1] == '2': raise Exception('BUG!') os._exit(0) if __name__ == '__main__': import afl afl.start() main()
  • 6.
    AFL config andrun # echo core > /proc/sys/kernel/core_pattern Maybe skip CPU freq is required: AFL_SKIP_CPUFREQ=1 or update CPUFREQ settings for CPUs: # echo performance | tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor $ py-afl-fuzz -m 500 -t 2000 -i in -o out -- python test.py
  • 8.
    Simple test results Crashfound: ./out/crashes/id:000000,sig:10,src:000000,op:havoc,rep:2 $ cat id:000000,sig:10,src:000000,op:havoc,rep:2 12
  • 9.
    Test compressed_rtf module importos import sys from compressed_rtf import compress, decompress def main(): data = sys.stdin.read() assert decompress(compress(data, compressed=True)) == data os._exit(0) if __name__ == '__main__': import afl afl.start() main()
  • 11.
    Other tools - SeePythonTestingToolsTaxonomy [5] - Hypothesis [10] - zzuf [11] - your own bicycle [6]
  • 12.
    Bug in marshalmodule Artem Smotrakov found a bug in marshal module with his own fuzzer [6, 8]: import marshal value = ('this is a string', [1, 2, 3, 4], ('more tuples', 1.0, 2.3, 4.5), 'this is yet another string') dump = marshal.dumps(value) data = bytearray(dump) data[10] = 40 data[4] = 16 data[103] = 143 data[97] = 245 data[78] = 114 data[35] = 188 marshal.loads(bytes(data))
  • 13.
    Bug in marshalmodule Artem Smotrakov found a bug in marshal module with his own fuzzer [6, 7, 8]:
  • 14.
    References 1. https://en.wikipedia.org/wiki/Fuzzing 2. http://lcamtuf.coredump.cx/afl/ 3.https://alexgaynor.net/2015/apr/13/introduction-to-fuzzing-in-python-with-afl/ 4. https://barro.github.io/2018/01/taking-a-look-at-python-afl/ 5. https://wiki.python.org/moin/PythonTestingToolsTaxonomy 6. https://blog.gypsyengineer.com/en/security/python-marshal-module-fuzzing.html 7. https://bugs.python.org/issue27826 8. https://github.com/artem-smotrakov/python-marshal-fuzzer 9. http://tomviner.co.uk/tag/conferences.html 10. https://hypothesis.works/ 11. http://caca.zoy.org/wiki/zzuf 12. https://fuzzing-project.org/