skipped 35 lines 36 36 37 37 - About Bug Bounties 38 38 - Aiven Bug Bounty program 39 - - My approach for huntings bugs through few examples 39 + - Step-by-step explanation of a few bug bounty reports 40 40 41 41 --- 42 42 43 43 # What are Bug Bounties? 44 44 45 - - Hackers rewarded for discovering security issues 46 - - Reward based on impact 45 + - Hackers rewarded for discovering and reporting exploitable security issues in the bug bounty program in - scope assets 46 + - Companies can create bug bounty programs for their assets on a managed platform (e.g, HackerOne, Intigriti) or create their own bug bounty platform (Google, Microsoft) 47 + 48 + <img src="img/hackerone_logo_black.png" style="height: 100px;position:absolute;top: 350px;right:50px"/> 49 + <img src="img/intigriti-full-logo-black.svg" style="height: 100px;position:absolute;top: 250px;right:500px;"/> 47 50 48 51 --- 49 52 skipped 36 lines 86 89 87 90 --- 88 91 89 - # Grafana RCE ( 1 ) 92 + # Grafana RCE 90 93 91 94 92 95 <img src="img/grafana_aiven_config.png" style="height:400px"/> skipped 8 lines 101 104 102 105 --- 103 106 104 - # Grafana RCE ( 2 ) 107 + # Grafana RCE 105 108 106 109 - Let's look at the Grafana documentation 107 110 <img src="img/grafana_doc1.png"/> skipped 6 lines 114 117 115 118 --- 116 119 117 - # Grafana RCE ( 3 ) 120 + # Grafana RCE 118 121 119 122 - Supports configuration via grafana.ini file: 120 123 skipped 21 lines 142 145 143 146 --- 144 147 145 - # Grafana RCE ( 3 ) 148 + # Grafana RCE 146 149 147 150 - Likely Aiven creates grafana.ini dynamically from user input 148 151 skipped 5 lines 154 157 155 158 --- 156 159 157 - # Grafana RCE ( 4 ) 160 + # Grafana RCE 158 161 159 162 - Q1: Can we edit unsupported configuration options by injecting newline characters? 160 163 - Q2: How this could be escalated to Remote Command Execution (RCE)? skipped 6 lines 167 170 168 171 --- 169 172 170 - # Grafana RCE ( 5 ) - Q1 173 + # Grafana RCE 171 174 172 175 - Testing for CRLF injection (\r\n) AKA newline injection 173 176 - Searched Aiven Github repositories in case something interesting was there skipped 9 lines 183 186 184 187 --- 185 188 186 - # Grafana RCE ( 6 ) - Q1 189 + # Grafana RCE - Q1 187 190 188 191 Example input validation entry: 189 192 ```json skipped 17 lines 207 210 208 211 --- 209 212 210 - # Grafana RCE ( 7 ) - Q1 213 + # Grafana RCE - Q1 211 214 212 215 SMTP server parameters missing regex validation. CRLF injection possible!!! 213 216 skipped 29 lines 243 246 244 247 --- 245 248 246 - # Grafana RCE ( x ) 249 + # Grafana RCE 247 250 248 251 - Q1: Can we edit unsupported configuration options by injecting newline characters? ✅ 249 252 - <b>Q2: How this could be escalated to Remote Command Execution (RCE)?</b> skipped 7 lines 257 260 258 261 --- 259 262 260 - # Grafana RCE ( 7 ) - Q2 263 + # Grafana RCE - Q2 261 264 262 265 <img src="img/grafana_rendering1.png"/> 263 266 skipped 5 lines 269 272 270 273 --- 271 274 272 - # Grafana RCE ( 8 ) - Q2 275 + # Grafana RCE - Q2 273 276 274 277 <img src="img/grafana_rendering2.png"/> 275 278 skipped 6 lines 282 285 283 286 --- 284 287 285 - # Grafana RCE ( x ) 288 + # Grafana RCE 286 289 287 290 - <https://peter.sh/experiments/chromium-command-line-switches/>: 288 291 <img src="img/grafana_rendering3.png"/> skipped 7 lines 296 299 297 300 --- 298 301 299 - # Grafana RCE ( x ) 302 + # Grafana RCE 300 303 301 304 - Verified that it works on local Grafana instance 302 305 - How to establish reverse shell: skipped 10 lines 313 316 314 317 --- 315 318 316 - # Grafana RCE ( 9 ) 319 + # Grafana RCE 317 320 318 321 - For some reason, could not pass white spaces, had to encode spaces using "$IFS" 319 322 - IFS env variable - Internal Field Seperator - can be used as space substitute skipped 11 lines 331 334 332 335 --- 333 336 334 - # Grafana RCE ( 9 ) 337 + # Grafana RCE 335 338 336 339 ```http 337 340 PUT /v1/project/PROJECT_NAME/service/GRAFANA_INSTANCE_NAME HTTP/1.1 skipped 24 lines 362 365 363 366 --- 364 367 365 - # Grafana RCE ( 10 ) 368 + # Grafana RCE 369 + 370 + - https://hackerone.com/reports/1200647 371 + 372 + <BarBottom title="hackerone.com/reports/1200647"> 373 + <Item text="@JJaaskela"> 374 + <carbon:logo-twitter /> 375 + </Item> 376 + </BarBottom> 377 + 378 + --- 379 + 380 + # Grafana RCE 381 + 382 + <video> 383 + <source src="videos/flink.mp4" type="video/mp4"> 384 + </video> 385 + 386 + <BarBottom title="hackerone.com/reports/1418891"> 387 + <Item text="@JJaaskela"> 388 + <carbon:logo-twitter /> 389 + </Item> 390 + </BarBottom> 391 + 392 + --- 393 + 394 + # Grafana RCE 366 395 367 396 <img src="img/report_grafana_reward.png"/> 368 397 skipped 52 lines 421 450 422 451 --- 423 452 424 - # Apache Flink RCE ( 2 ) 453 + # Apache Flink RCE 425 454 426 455 Apache Flink Rest API documentation: 427 456 skipped 122 lines 550 579 </Item> 551 580 </BarBottom> 552 581 582 + --- 583 + 584 + # Apache Flink RCE 585 + 586 + - https://hackerone.com/reports/1418891 587 + - https://github.com/Jarijaas/helsec-1103/blob/master/pocs/flink.py 588 + 589 + <BarBottom title="hackerone.com/reports/1418891"> 590 + <Item text="@JJaaskela"> 591 + <carbon:logo-twitter /> 592 + </Item> 593 + </BarBottom> 553 594 554 595 --- 555 596 556 597 # Apache Flink RCE 557 598 558 - <img src="img/aiven-flink-rce.png"/> 599 + <video> 600 + <source src="videos/flink.mp4" type="video/mp4"> 601 + </video> 559 602 560 603 <BarBottom title="hackerone.com/reports/1418891"> 561 604 <Item text="@JJaaskela"> skipped 1 lines 563 606 </Item> 564 607 </BarBottom> 565 608 566 - < ! -- 609 + - -- 610 + 567 611 # Apache Flink RCE 568 612 569 - - GET /jars/:jarId/plan was removed in Flink 1.16 (28 Oct 2022) release 613 + <img src="img/aiven-flink-rce.png"/> 570 614 571 615 <BarBottom title="hackerone.com/reports/1418891"> 572 616 <Item text="@JJaaskela"> 573 617 <carbon:logo-twitter /> 574 618 </Item> 575 619 </BarBottom> 576 - --> 577 620 578 621 --- 579 622 skipped 147 lines 727 770 728 771 --- 729 772 730 - # Kafka Connect RCE - JDBC SQLite config 731 - 732 - ```python 733 - connector_url = f"{kafka_connect_api_baseurl}/connectors/{connector_name}" 734 - 735 - payload = json.dumps({ 736 - "connector.class": "io.aiven.connect.jdbc.JdbcSinkConnector", 737 - "connection.url": f"jdbc:sqlite:/tmp/test.db", 738 - "name":connector_name, 739 - "topics": topic_name, 740 - "key.converter": "org.apache.kafka.connect.storage.StringConverter", 741 - "value.converter": "org.apache.kafka.connect.json.JsonConverter", 742 - "value.converter.schemas.enable": "true", 743 - "auto.create": "true" # Create tables automatically 744 - }) 745 - headers = { 746 - 'Content-Type': 'application/json' 747 - } 748 - requests.request("PUT", f"{connector_url}/config", headers=headers, data=payload, auth=(kafka_user, kafka_password)) 749 - ``` 750 - 751 - <BarBottom title="hackerone.com/reports/1547877"> 752 - <Item text="@JJaaskela"> 753 - <carbon:logo-twitter /> 754 - </Item> 755 - </BarBottom> 756 - 757 - --- 758 - 759 - # Kafka Connect RCE - JDBC SQLite Kafka topic message 773 + # Kafka Connect RCE 760 774 761 - ```python 762 - producer.send(topic_name, json.dumps( 763 - { 764 - "schema": { 765 - "type": "struct", 766 - "fields": [{ 767 - "field": "payload", 768 - "type": "bytes", 769 - "optional": False 770 - }] 771 - }, 772 - "payload": { 773 - # JsonConverter uses com.fasterxml.jackson, which supports binary values as base64 encoded string 774 - "payload": base64.b64encode(jar_contents).decode('utf-8') 775 - } 776 - } 777 - ).encode('utf-8')) 778 - ``` 775 + - https://hackerone.com/reports/1547877 776 + - https://github.com/Jarijaas/helsec-1103/blob/master/pocs/jdbc.py 779 777 780 778 <BarBottom title="hackerone.com/reports/1547877"> 781 779 <Item text="@JJaaskela"> skipped 29 lines 811 809 812 810 --- 813 811 814 - # That's it 812 + # Thank you! 815 813 816 814 - Any questions? 815 + - Slides + PoC scripts: [^1] 816 + 817 + [^1]: https://github.com/Jarijaas/helsec-1103 817 818 818 819 <BarBottom title="Thank you!"> 819 820 <Item text="@JJaaskela"> skipped 6 lines