proxychains-ng
proxychains-ng copied to clipboard
php curl module ignores proxychains
try this simple script:
<?php
echo "file_get_contents:\n";
echo file_get_contents("http://ifconfig.me/ip");
echo "curl:\n";
$ch=curl_init();
curl_setopt($ch,CURLOPT_URL,"http://ifconfig.me/ip");
curl_setopt($ch,CURLOPT_HEADER,0);
curl_exec($ch);
curl_close($ch);
assume that my real ip is 123.45.67.89 and socks proxy ip is 10.10.10.10 without proxychains:
# php php_curl.php
file_get_contents:
123.45.67.89
curl:
123.45.67.89
with proxychains:
# proxychains php php_curl.php
[proxychains] config file found: /etc/proxychains.conf
[proxychains] preloading /usr/lib/libproxychains4.so
file_get_contents:
10.10.10.10
curl:
123.45.67.89
i.e. curl was not proxified even with proxychains library preloaded.
programs that launch other programs are tricky to deal with. maybe environment variables get cleared. try using export LD_PRELOAD=/path/to/proxychains4.so in the shell previous to running your php script. also proxychains works only with dynamically loaded stuff. maybe php is statically linked against curl ? try running gdb --args proxychains4 php myscript.php and put a breakpoint on "connect", and then look at the backtrace whenever the bp is hit.
i did some tests and the following happens: for the php connect itself, libc.so is used in the ordinary way, everything works as expected. for cul, php dlopen()'s curl.so, which opens libcurl.so. for some reason the glibc dynlinker does not hook the connect() symbol for libcurl.so this seems to be a bug in glibc's dynlinker, as it works as expected with musl libc dynlinker. in other words, running your php script using musl libc as system libc, 10.10.10.10 is returned for both calls.
can i use musl libc instead of gnu libc in centos 6? i've tried LD_PRELOAD but it has not fixed the issue.
yeah, you can use musl libc as a secondary libc, but you need to compile everything involved from source using the provided musl-gcc wrapper, that means zlib, openssl, php, curl, and proxychains (everything called must be using the same libc)
here are build recipes for musl (configure flags etc) https://github.com/rofl0r/sabotage/blob/master/pkg/curl https://github.com/rofl0r/sabotage/blob/master/pkg/php https://github.com/rofl0r/sabotage/blob/master/pkg/zlib https://github.com/rofl0r/sabotage/blob/master/pkg/openssl
many thanks for your effort but i'm afraid i wont be able to install all those packages. could you please suggest some simplier workaround?
the simplest thing in your situation is probably to use the built-in proxy support of curl i.e. adapt your php scripts so that they all use the same proxy than proxychains (maybe it even works with an environment variable)
alternatively you could either scratch php and use C, or download a precompiled sabotage linux rootfs from http://mirror.wzff.de/sabotage/ and extract it into some directory (read the http://mirror.wzff.de/sabotage/README_sabotage_images.txt for how to extract the image files) then chroot into that dir and use the php scripts from inside the chroot with musl.
I'm having the same issue on Debian, but in OSX that issue doesn't happen. Any thoughts ?
it's a bug in GLIBCs dynlinker. someone would need to stand up and report the issue on their bugtracker. this comment explains what happens.
i've created a minimal testcase to reproduce the issue: https://0x0.st/fdc.gz
it's 3 small C files and a build.sh. when you run build.sh, you should see the output
hooked
hooked
however on GLIBC it probably prints hooked only once.
can anyone test this ? i don't have a system with GLIBC.
when we have it confirmed, someone can take the testcase and open a bug report on the GLIBC bugtracker.
app.c
#define _GNU_SOURCE
#include <stdio.h>
#include <dlfcn.h>
typedef void (*func)(void);
int main() {
puts("hello world");
void *h = dlopen("./dlopened.so", RTLD_NOW);
func doit = dlsym(h, "doit");
doit();
}
build.sh
#!/bin/sh
gcc preload.c -Wall -shared -fPIC -ldl -lpthread -o preload.so
gcc dlopened.c -Wall -shared -fPIC -ldl -o dlopened.so
gcc app.c -Wall -ldl -o app
LD_PRELOAD=./preload.so ./app
# should print hooked twice.
# if it doesn't, dynlinker is broken
dlopened.c
#include <stdio.h>
void doit(void) {
puts("puts from dlopened .so");
}
preload.c
#define _GNU_SOURCE
#include <pthread.h>
#include <dlfcn.h>
pthread_once_t init_once = PTHREAD_ONCE_INIT;
typedef int (*putsfunc)(const char*);
putsfunc origputs;
static void init(void) {
origputs = dlsym(RTLD_NEXT, "puts");
}
__attribute__((constructor))
static void gcc_init(void) {
pthread_once(&init_once, init);
}
int puts(const char* s) {
origputs("hooked");
return 1;
}
On 2017-01-15 07:01, rofl0r wrote:
i've created a minimal testcase to reproduce the issue: https://0x0.st/fDK.gz it's 3 small C files and a build.sh. when you run
build.sh, you should see the outputhooked hookedhowever on GLIBC it probably prints
hookedonly once. can anyone test this ? i don't have a system with GLIBC. when we have it confirmed, someone can take the testcase and open a bug report on the GLIBC bugtracker.
problem:
dlopen_bug> gcc preload.c -Wall -shared -fPIC -ldl -o preload.so
preload.c: In function ‘init’:
preload.c:9:19: error: ‘RTLD_NEXT’ undeclared (first use in this
function) origputs = dlsym(RTLD_NEXT, "puts"); ^
fix:
gcc preload.c -D_GNU_SOURCE -Wall -shared -fPIC -ldl -o preload.so
or add a line:
--- preload.c 2017-01-15 14:13:06.951753115 +0700
+++ preload_fix.c 2017-01-15 14:13:03.459753218 +0700
@@ -1,3 +1,4 @@
+#define _GNU_SOURCE
#include <pthread.h>
#include <dlfcn.h>
pthread_once_t init_once = PTHREAD_ONCE_INIT;
problem:
dlopen_bug> sh build.sh
app.c: In function ‘main’:
app.c:11:1: warning: control reaches end of non-void function
[-Wreturn-type] } ^ ./app: symbol lookup error: ./preload.so: undefined symbol: pthread_once
fix:
gcc preload.c -D_GNU_SOURCE -lpthread -Wall -shared -fPIC -ldl -o
preload.so
But in the end it surprisingly works on Centos 6.8 gcc 4.4.7 glibc 2.12 (system of the test case with php and curl) and openSUSE 13.2 gcc 4.8.3 glibc 2.19:
dlopen_bug> sh build.sh
app.c: In function ‘main’:
app.c:11:1: warning: control reaches end of non-void function
[-Wreturn-type] } ^ hooked hooked
thanks. what was the output of the testcase once you got it to run, @kai-rn ?
Github broke my email formatting, press on "..." icon to see the rest of the email. The output is as follows:
But in the end it surprisingly works on Centos 6.8 gcc 4.4.7 glibc 2.12 (system of the test case with php and curl) and openSUSE 13.2 gcc 4.8.3 glibc 2.19:
dlopen_bug> sh build.sh app.c: In function ‘main’: app.c:11:1: warning: control reaches end of non-void function [-Wreturn-type] } ^ hooked hooked
damn. even when you replace RTLD_NOW with RTLD_LAZY in app.c ?
On 2017-01-15 19:28, rofl0r wrote:
damn. even when you replace
RTLD_NOWwithRTLD_LAZYin app.c ?
still works.
hooked hooked